├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitattributes ├── .github └── workflows │ └── validate-workflow.yml ├── .gitignore ├── .gitmodules ├── .husky └── pre-commit ├── .node-version ├── .npmignore ├── .npmrc ├── .prettierignore ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── SECURITY.md ├── apps ├── app-config │ ├── README.md │ ├── _generateConnectorLists.ts │ ├── _generateDocs.bin.ts │ ├── backendConfig.ts │ ├── bootstrap.ts │ ├── connector-envs.ts │ ├── connectors │ │ ├── connectors.client.ts │ │ ├── connectors.def.ts │ │ ├── connectors.merged.ts │ │ ├── connectors.server.ts │ │ └── meta.js │ ├── constants.ts │ ├── env.ts │ ├── package.json │ └── register.node.ts ├── cli │ ├── README.md │ ├── _cli.ts │ ├── airbyte-plaid-connector.ts │ ├── cli-utils.ts │ ├── package.json │ ├── pgMigrator-cli.ts │ ├── sync-test-old.ts │ ├── sync-test.ts │ └── venice-cli.ts ├── gondola │ ├── .gitignore │ ├── app │ │ ├── global.css │ │ ├── layout.tsx │ │ └── page.tsx │ ├── next-env.d.ts │ ├── next.config.js │ ├── next.config.ts │ ├── package.json │ ├── postcss.config.js │ ├── sentry.properties │ ├── tailwind.config.ts │ └── tsconfig.json └── web │ ├── .env.example │ ├── .gitignore │ ├── @types │ └── node-http-proxy-json.d.ts │ ├── app │ ├── (admin) │ │ ├── (authenticated) │ │ │ ├── Sidebar.tsx │ │ │ ├── TopNav.tsx │ │ │ ├── api-access │ │ │ │ ├── graphql │ │ │ │ │ └── page.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── rest │ │ │ │ │ └── page.tsx │ │ │ ├── connector-configs │ │ │ │ ├── ConnectorConfigPage.tsx │ │ │ │ ├── ConnectorConfigSheet.tsx │ │ │ │ └── page.tsx │ │ │ ├── end-users │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ ├── magic-link │ │ │ │ └── page.tsx │ │ │ ├── metrics │ │ │ │ └── page.tsx │ │ │ ├── page.tsx │ │ │ ├── pipelines │ │ │ │ └── page.tsx │ │ │ ├── resources │ │ │ │ ├── ResourcesPage.tsx │ │ │ │ ├── [resourceId] │ │ │ │ │ ├── playground │ │ │ │ │ │ ├── PlaygroundPage.tsx │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── sql │ │ │ │ │ │ ├── SqlPage.tsx │ │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ └── settings │ │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── org │ │ │ └── [slug] │ │ │ │ ├── layout-client.tsx │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ ├── sign-in │ │ │ └── page.tsx │ │ └── sign-up │ │ │ └── page.tsx │ ├── api │ │ ├── me │ │ │ └── route.ts │ │ ├── resources │ │ │ └── [resourceId] │ │ │ │ └── sql │ │ │ │ └── route.ts │ │ └── v0-edge │ │ │ └── [...trpc] │ │ │ └── route.ts │ ├── connect │ │ ├── ConnectPage.tsx │ │ ├── SetCookieAndRedirect.tsx │ │ ├── callback │ │ │ ├── CallbackEffect.tsx │ │ │ └── page.tsx │ │ └── page.tsx │ ├── demo │ │ └── page.tsx │ ├── global.css │ ├── hello │ │ └── page.tsx │ └── layout.tsx │ ├── components │ ├── ClientRoot.tsx │ ├── FullScreenCenter.tsx │ ├── NoSSR.tsx │ ├── PipelineSheet.tsx │ ├── RedirectTo.tsx │ ├── ResourceSheet.tsx │ ├── SuperHydrate.tsx │ └── viewer-context.tsx │ ├── inngest │ ├── cli.ts │ ├── functions.ts │ └── routines.ts │ ├── lib-client │ ├── analytics-browser.ts │ ├── copyToClipboard.ts │ ├── react-query-client.ts │ ├── supabase-realtime.ts │ ├── trpcReact.ts │ └── ui-utils.ts │ ├── lib-common │ └── schemas.ts │ ├── lib-server │ ├── analytics-server.ts │ ├── appRouter.ts │ ├── index.ts │ ├── procedures.ts │ ├── sentry-client.ts │ ├── server-component-helpers.ts │ ├── server-helpers.ts │ └── supabase-proxy.ts │ ├── middleware.ts │ ├── migrations │ ├── 0_setup-ulid.sql │ ├── 1_create-table.sql │ ├── 2023-01-06_rls.sql │ ├── 2023-01-25_rename_to_raw.sql │ ├── 2023-01-27_rename_connection_to_resource.sql │ ├── 2023-02-01_user_apikey_index.sql │ ├── 2023-02-02_add_connection_name.sql │ ├── 2023-02-03_graphql_comments.sql │ ├── 2023-02-22_institution_rls.sql │ ├── 2023-02-27_remove_database_users.sql │ ├── 2023-02-27_revoke_anon.sql │ ├── 2023-02-28_1307_enable_realtime_publications.sql │ ├── 2023-02-28_1954_remove_public_uid.sql │ ├── 2023-04-02_0140_admin_user.sql │ ├── 2023-04-04_0211_pgrest_pre_request.sql │ ├── 2023-04-22_1503_add_end_user_id_remove_ledger_id.sql │ ├── 2023-04-23_0735_default_id_prefix.sql │ ├── 2023-04-23_0753_materialized_cte_over_pre_request.sql │ ├── 2023-04-29_1549_multi_tenant.sql │ ├── 2023-05-22_2146_migrate_plaid_config.sql │ ├── 2023-10-23_0313_integration_env_name.sql │ ├── 2023-10-29_2125_integration_provider_name_grant.sql │ ├── 2023-11-14_0109_pipeline_disabled.sql │ ├── 2023-11-20_1923_connector_name.sql │ ├── 2023-11-21_0821_integration_to_connector_config.sql │ ├── 2023-11-21_0934_institution_to_integration.sql │ ├── 2023-11-24_0008_connector_config_src_dest.sql │ ├── 2023-11-25_0545_connector_config_src_dest_top_level.sql │ ├── 2023-11-25_0836_connector_config_incoming_outgoing.sql │ ├── 2023-11-30_2212_add_metadata.sql │ └── 2023-11-30_2310_drop_end_user_access.sql │ ├── migrations_wip │ ├── 2023-01-06_connection-user.sql │ ├── 2023-01-07_create-views.sql │ ├── 2023-02-27_2252_postgres-follow-privileges.sql │ ├── 2023-02-28_1433_database_webhooks.sql │ ├── 2023-04-22_1501_pre_request_to_mcte.sql │ └── 2023-04-22_2039_end_user_table.sql │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── pages │ └── api │ │ ├── debug.ts │ │ ├── graphql │ │ └── [[...graphql]].ts │ │ ├── inngest.ts │ │ ├── rest │ │ └── [[...rest]].ts │ │ ├── sentry_sample_error.ts │ │ ├── trpc │ │ ├── [...trpc].ts │ │ └── index.ts │ │ ├── v0 │ │ ├── [...trpc].ts │ │ └── index.ts │ │ └── webhook │ │ └── [[...webhook]].ts │ ├── postcss.config.js │ ├── public │ ├── _assets │ │ ├── logo-airtable.png │ │ ├── logo-airtable.svg │ │ ├── logo-apollo.svg │ │ ├── logo-brex.png │ │ ├── logo-discord.svg │ │ ├── logo-firebase.png │ │ ├── logo-heron.png │ │ ├── logo-import.png │ │ ├── logo-mercury.png │ │ ├── logo-mongodb.png │ │ ├── logo-moota.png │ │ ├── logo-onebrick.png │ │ ├── logo-outreach.svg │ │ ├── logo-postgres.png │ │ ├── logo-qbo.svg │ │ ├── logo-ramp.png │ │ ├── logo-salesloft.svg │ │ ├── logo-saltedge.png │ │ ├── logo-spreadsheet.png │ │ ├── logo-stripe.png │ │ ├── logo-teller.svg │ │ ├── logo-twenty.svg │ │ ├── logo-venmo.png │ │ ├── logo-webhook.png │ │ ├── logo-wise.png │ │ ├── logo-xero.svg │ │ └── logo-yodlee.png │ ├── chase-logo.svg │ ├── copy-icon.svg │ ├── db-links-line.svg │ ├── favicon.svg │ ├── fidelity-logo.svg │ ├── heron-logo.png │ ├── institution-placeholder.svg │ ├── mergeLogo.png │ ├── netsuiteLogo.png │ ├── pipeline-in.svg │ ├── pipeline-out.svg │ ├── plaidLogo.png │ ├── qboLogo.png │ ├── requestLogo.png │ ├── stripeLogo.png │ ├── venice-database.png │ ├── venice-logo-black.svg │ ├── venice-logo-white-no-bg.svg │ └── wells-fargo-logo.svg │ ├── schema.sql │ ├── sentry.client.config.ts │ ├── sentry.edge.config.ts │ ├── sentry.properties │ ├── sentry.server.config.ts │ ├── supabase │ ├── .gitignore │ ├── config.toml │ ├── seed.sql │ └── supabase.gen.d.ts │ ├── tailwind.config.ts │ ├── themes.ts │ ├── tsconfig.json │ └── vcommands │ ├── GlobalCommandBar.tsx │ ├── vcommand-components.tsx │ ├── vcommand-context.tsx │ └── vcommand-definitions.ts ├── bin ├── shdotenv └── venice.ts ├── connectors ├── LICENSE ├── README.md ├── connector-airtable │ ├── AirtableClient.ts │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-alphavantage │ ├── alphavantage.d.ts │ ├── alphavantageClient.ts │ ├── index.ts │ └── package.json ├── connector-apollo │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-beancount │ ├── __snapshots__ │ │ └── beancountConverters.spec.ts.snap │ ├── bean-fs-utils.ts │ ├── beancount.d.ts │ ├── beancountConverters.spec.ts │ ├── beancountConverters.ts │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-brex │ ├── BrexClient.ts │ ├── README.md │ ├── __generated__ │ │ ├── transactions.gen.ts │ │ └── transactions.openapi.json │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-copilot │ ├── CopilotClient.ts │ └── package.json ├── connector-debug │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-discord │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-expensify │ ├── expensify.d.ts │ ├── expensifyClient.ts │ ├── index.ts │ └── package.json ├── connector-firebase │ ├── MultiBatch.ts │ ├── def.ts │ ├── firebase-types.ts │ ├── firebase-utils.ts │ ├── firebaseAuth.ts │ ├── index.ts │ ├── package.json │ ├── register.node.ts │ └── server.ts ├── connector-foreceipt │ ├── ForeceiptClient.ts │ ├── def.ts │ ├── foreceipt-utils.ts │ ├── foreceipt.d.ts │ ├── index.ts │ ├── package.json │ ├── register.node.ts │ └── server.ts ├── connector-fs │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-heron │ ├── HeronClient.ts │ ├── README.md │ ├── def.ts │ ├── heron.gen.ts │ ├── heron.openapi.json │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-lunchmoney │ ├── def.ts │ ├── index.ts │ ├── lunchmoneyClient.ts │ ├── package.json │ └── server.ts ├── connector-mercury │ ├── def.ts │ ├── lib │ │ └── mercury.gen.ts │ └── package.json ├── connector-merge │ ├── MergeClient.ts │ ├── README.md │ ├── client.ts │ ├── def.ts │ ├── index.ts │ ├── merge-logo.svg.ts │ ├── merge.accounting.gen.ts │ ├── package.json │ └── server.ts ├── connector-mongodb │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-moota │ ├── def.ts │ ├── index.ts │ ├── moota.d.ts │ ├── mootaClient.ts │ ├── package.json │ └── server.ts ├── connector-notion │ ├── notion.openapi.gen.d.ts │ ├── notion.openapi.gen.yaml │ └── package.json ├── connector-onebrick │ ├── OneBrickClient.ts │ ├── client.ts │ ├── def.ts │ ├── index.ts │ ├── onebrick-utils.ts │ ├── onebrick.gen.ts │ ├── package.json │ └── server.ts ├── connector-outreach │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-plaid │ ├── PlaidClient.ts │ ├── README.md │ ├── client.ts │ ├── def.ts │ ├── index.ts │ ├── legacy │ │ └── plaid-helpers.ts │ ├── package.json │ ├── plaid-utils.ts │ ├── plaid.types.ts │ ├── request.noop.ts │ └── server.ts ├── connector-postgres │ ├── @types │ │ └── slonik-interceptor-preset.d.ts │ ├── def.ts │ ├── index.ts │ ├── makePostgresClient.spec.ts │ ├── makePostgresClient.ts │ ├── package.json │ └── server.ts ├── connector-qbo │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-ramp │ ├── RampClient.ts │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-salesloft │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-saltedge │ ├── def.ts │ ├── index.ts │ ├── package.json │ ├── saltedge.d.ts │ ├── saltedgeClient.ts │ └── server.ts ├── connector-splitwise │ ├── SplitwiseClientNext.ts │ ├── def.ts │ ├── index.ts │ ├── package.json │ ├── server.ts │ └── splitwise-schema.ts ├── connector-spreadsheet │ ├── RowIdMaker.spec.ts │ ├── RowIdMaker.ts │ ├── def.ts │ ├── formats │ │ ├── format-alliant-credit-union.ts │ │ ├── format-apple-card.ts │ │ ├── format-bbva-mexico.ts │ │ ├── format-brex-cash.ts │ │ ├── format-brex.ts │ │ ├── format-capitalone-bank.ts │ │ ├── format-capitalone.ts │ │ ├── format-coinbase.ts │ │ ├── format-coinkeeper.ts │ │ ├── format-etrade.ts │ │ ├── format-first-republic.ts │ │ ├── format-ramp.ts │ │ ├── format-wise.ts │ │ └── index.ts │ ├── index.ts │ ├── makeImportFormat.ts │ ├── package.json │ └── server.ts ├── connector-stripe │ ├── StripeClient.ts │ ├── def.ts │ ├── index.ts │ ├── package.json │ ├── server.ts │ └── stripe.gen.ts ├── connector-teller │ ├── TellerClient.ts │ ├── client.ts │ ├── def.ts │ ├── index.ts │ ├── institutionWsResponse.json │ ├── package.json │ └── server.ts ├── connector-toggl │ ├── TogglCient.ts │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-twenty │ ├── crm-unifiedModels.ts │ ├── def.ts │ ├── index.ts │ ├── package.json │ ├── sdk.spec.ts │ ├── server.spec.ts │ └── server.ts ├── connector-venmo │ ├── VenmoClient.ts │ ├── VenmoProvider.ts │ ├── def.ts │ ├── index.ts │ ├── package.json │ ├── venmo-helpers.ts │ ├── venmo-v5.d.ts │ └── venmo.d.ts ├── connector-vercel │ ├── package.json │ ├── vercel.openapi.gen.d.ts │ └── vercel.openapi.gen.yaml ├── connector-webhook │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-wise │ ├── WiseClient.ts │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts ├── connector-xero │ ├── def.ts │ ├── index.ts │ ├── package.json │ └── server.ts └── connector-yodlee │ ├── README.md │ ├── YodleeClient.ts │ ├── client.ts │ ├── def.ts │ ├── fastlink.d.ts │ ├── index.ts │ ├── package.json │ ├── request.noop.ts │ ├── server.ts │ ├── yodlee-utils.ts │ ├── yodlee.deprecated.d.ts │ ├── yodlee.oas.d.ts │ ├── yodlee.oas.json │ └── yodlee.types.ts ├── docker-compose.yml ├── docs ├── api-reference │ ├── connect │ │ ├── post-connectmagic-link.mdx │ │ └── post-connecttoken.mdx │ ├── connectors │ │ ├── get-connector-1.mdx │ │ ├── get-connector-oas.mdx │ │ ├── get-connector-schemas.mdx │ │ └── get-connector.mdx │ ├── core │ │ ├── delete-coreconnector_config.mdx │ │ ├── delete-corepipeline.mdx │ │ ├── delete-coreresource.mdx │ │ ├── get-coreconnector_config-1.mdx │ │ ├── get-coreconnector_config.mdx │ │ ├── get-coreconnector_config_info.mdx │ │ ├── get-corepipeline.mdx │ │ ├── get-coreresource-1.mdx │ │ ├── get-coreresource.mdx │ │ ├── patch-coreresource.mdx │ │ ├── post-coreconnector_config.mdx │ │ ├── post-coreresource-source_sync.mdx │ │ └── post-coreresource.mdx │ ├── get-openapijson.mdx │ ├── index.json │ ├── internal │ │ ├── get-debugraw-schemas.mdx │ │ ├── health-check.mdx │ │ └── post-passthrough.mdx │ └── verticals │ │ ├── get-verticalsaccountingaccount.mdx │ │ ├── get-verticalsaccountingexpense.mdx │ │ ├── get-verticalsaccountingvendor.mdx │ │ ├── get-verticalsinvestmentaccount.mdx │ │ ├── get-verticalsinvestmentholding.mdx │ │ ├── get-verticalsinvestmentsecurity.mdx │ │ ├── get-verticalsinvestmenttransaction.mdx │ │ ├── get-verticalsptaaccount.mdx │ │ ├── get-verticalsptacommodity.mdx │ │ └── get-verticalsptatransaction.mdx ├── images │ ├── background.png │ ├── favicon.png │ ├── logo │ │ ├── venice-black-logo.svg │ │ └── venice-white-logo.svg │ ├── models.png │ ├── models.svg │ └── synced.svg ├── mint.json ├── mint.ts ├── models.prisma ├── package.json ├── quickstart │ ├── features.mdx │ ├── quickstart.mdx │ └── use-cases.mdx ├── samples │ ├── banking-test.ts │ ├── proxy-test.mts │ ├── sales-engagement-test.ts │ └── sample.ts ├── support │ ├── attribution.mdx │ ├── contact-us.mdx │ ├── custom-integration.mdx │ └── faq.mdx ├── technical │ ├── apis.mdx │ ├── architecture.mdx │ ├── data-models.mdx │ ├── deploy-locally.mdx │ ├── deploy-to-cloud.mdx │ └── open-source.mdx └── venice.oas.json ├── env.d.ts ├── github ├── github.png ├── join-community.png ├── read-docs.png └── sign-up.png ├── jest.config.js ├── kits ├── cdk │ ├── LICENSE │ ├── base-links.ts │ ├── connector-meta.types.ts │ ├── connector-utils.ts │ ├── connector.types.ts │ ├── entity-links.ts │ ├── frontend-utils.tsx │ ├── id.types.ts │ ├── index.ts │ ├── metaForConnector.ts │ ├── models.ts │ ├── nango │ │ ├── NangoClient.spec.ts │ │ ├── NangoClient.ts │ │ ├── index.ts │ │ ├── nangoProxyLink.spec.ts │ │ ├── nangoProxyLink.ts │ │ └── oauthConnector.ts │ ├── package.json │ ├── protocol.ts │ ├── sync.ts │ ├── verticals.ts │ └── viewer.ts ├── connect │ ├── .gitignore │ ├── .npmignore │ ├── index.ts │ ├── package.json │ ├── src │ │ ├── common.ts │ │ ├── embed-react.tsx │ │ ├── index.ts │ │ └── popup.ts │ └── tsconfig.json ├── sdk │ ├── .npmignore │ ├── createSdk.ts │ ├── index.ts │ ├── package.json │ ├── tsconfig.json │ ├── venice.oas.d.ts │ └── venice.oas.json └── vdk │ ├── index.ts │ ├── new-mapper.spec.ts │ ├── new-mapper.ts │ └── package.json ├── logo.png ├── package.json ├── packages ├── engine-backend │ ├── context.ts │ ├── events.ts │ ├── index.ts │ ├── package.json │ ├── parseWebhookRequest.ts │ ├── router │ │ ├── _base.ts │ │ ├── _schemas.ts │ │ ├── adminRouter.ts │ │ ├── connectorConfigRouter.ts │ │ ├── connectorRouter.ts │ │ ├── endUserRouter.ts │ │ ├── index.ts │ │ ├── pipelineRouter.ts │ │ ├── protectedRouter.ts │ │ ├── publicRouter.ts │ │ ├── resourceRouter.ts │ │ └── systemRouter.ts │ ├── services │ │ ├── NoopMetaService.ts │ │ ├── dbService.ts │ │ ├── index.ts │ │ ├── kvStore.ts │ │ ├── makeMetaLinks.ts │ │ ├── metaService.ts │ │ └── sync-service.ts │ └── types.ts ├── engine-frontend │ ├── TRPCProvider.tsx │ ├── VeniceConnect.tsx │ ├── index.ts │ ├── lib │ │ └── useGetter.ts │ └── package.json ├── meta-service-airbyte │ ├── Dockerfile │ ├── Dockerfile.dockerignore │ ├── READMD.md │ ├── airbyte-sdk.ts │ ├── airbyteMetaService.ts │ ├── api │ │ ├── airbyte-api-connections.gen.d.ts │ │ ├── airbyte-api-connections.oas.json │ │ ├── airbyte-api-destinations.gen.d.ts │ │ ├── airbyte-api-destinations.oas.json │ │ ├── airbyte-api-health.gen.d.ts │ │ ├── airbyte-api-health.oas.json │ │ ├── airbyte-api-jobs.gen.d.ts │ │ ├── airbyte-api-jobs.oas.json │ │ ├── airbyte-api-sources.gen.d.ts │ │ ├── airbyte-api-sources.oas.json │ │ ├── airbyte-api-streams.gen.d.ts │ │ ├── airbyte-api-streams.oas.json │ │ ├── airbyte-api-workspaces.gen.d.ts │ │ ├── airbyte-api-workspaces.oas.json │ │ ├── airbyte-private-api.gen.d.ts │ │ └── airbyte-private-api.oas.json │ ├── bin │ │ └── yaml2json.js │ ├── index.ts │ ├── makeAirbyteConnector.ts │ ├── package.json │ ├── protocol │ │ ├── low-code-connector.gen.ts │ │ ├── low-code-connector.oas.json │ │ ├── protocol.gen.ts │ │ ├── protocol.oas.json │ │ └── protocol.ts │ ├── redocly.yaml │ ├── sample │ │ ├── configured-catalog.json │ │ └── src-config.json │ └── utils.ts ├── meta-service-fs │ ├── index.ts │ ├── makeFsKVStore.ts │ └── package.json ├── meta-service-postgres │ ├── index.ts │ ├── makePostgresMetaService.ts │ └── package.json ├── meta-service-redis │ ├── index.ts │ ├── package.json │ └── redisKvStore.ts ├── ui │ ├── LICENSE │ ├── command │ │ ├── command-components.tsx │ │ ├── command-fns.spec.ts │ │ ├── command-fns.ts │ │ ├── command-types.ts │ │ └── index.ts │ ├── components │ │ ├── CodeEditor.tsx │ │ ├── DataGrid.tsx │ │ ├── DataTable.tsx │ │ ├── EffectContainer.tsx │ │ ├── Icon.tsx │ │ ├── Kbd.tsx │ │ ├── LoadingText.tsx │ │ ├── SchemaForm.tsx │ │ ├── SchemaSheet.tsx │ │ └── index.ts │ ├── domain-components │ │ ├── ConnectorCard.tsx │ │ ├── ResourceCard.tsx │ │ └── index.ts │ ├── hooks │ │ ├── index.ts │ │ ├── useConstant.ts │ │ ├── useWhyDidYouUpdate.ts │ │ └── useWithToast.ts │ ├── index.ts │ ├── package.json │ ├── shadcn │ │ ├── AlertDialog.tsx │ │ ├── Badge.tsx │ │ ├── Breadcrumb.tsx │ │ ├── Button.tsx │ │ ├── Card.tsx │ │ ├── Checkbox.tsx │ │ ├── Combobox.tsx │ │ ├── Command.tsx │ │ ├── Dialog.tsx │ │ ├── DropdownMenu.tsx │ │ ├── Input.tsx │ │ ├── Label.tsx │ │ ├── Popover.tsx │ │ ├── ScrollArea.tsx │ │ ├── Separator.tsx │ │ ├── Sheet.tsx │ │ ├── Table.tsx │ │ ├── Toast.tsx │ │ ├── Toaster.tsx │ │ └── index.ts │ └── utils.ts └── util │ ├── @types │ └── blossomfinance__iso-4217-currencies.d.ts │ ├── BehaviorObservable.ts │ ├── LICENSE │ ├── amount-utils.spec.ts │ ├── amount-utils.ts │ ├── array-utils.ts │ ├── balance-utils.ts │ ├── converter-utils.ts │ ├── date-utils.spec.ts │ ├── date-utils.ts │ ├── debug-utils.ts │ ├── di-utils.ts │ ├── env-utils.spec.ts │ ├── env-utils.ts │ ├── error-utils.ts │ ├── formatting-amount.spec.ts │ ├── formatting-amount.ts │ ├── formatting-number.ts │ ├── fs-utils.ts │ ├── function-utils.ts │ ├── http │ ├── http-utils.ts │ ├── index.ts │ ├── makeHttpClient.ts │ ├── makeOpenApiClient.ts │ └── oauth-utils.ts │ ├── id-utils.ts │ ├── immutable-utils.ts │ ├── index.ts │ ├── injected-utils.ts │ ├── iterable-utils.spec.ts │ ├── iterable-utils.ts │ ├── json-utils.ts │ ├── jsonschema-nodewalker.ts │ ├── logging-utils.ts │ ├── math-utils.ts │ ├── object-utils.spec.ts │ ├── object-utils.ts │ ├── observable-utils.ts │ ├── package.json │ ├── perf-utils.ts │ ├── promise-utils.ts │ ├── proxy-utils.spec.ts │ ├── proxy-utils.ts │ ├── schrono │ ├── MPDate.ts │ ├── MPInterval.spec.ts │ ├── MPInterval.ts │ ├── __snapshots__ │ │ └── simple-schedule.spec.ts.snap │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ └── schrono.spec.ts.snap │ │ ├── iso-date.spec.ts │ │ ├── natural-date.spec.ts │ │ └── schrono.spec.ts │ ├── chrono-parsers │ │ ├── RelativeDateFormatParser.ts │ │ ├── TimeUnitCasualRelativeFormatParser.ts │ │ └── chrono-parser-utils.ts │ ├── index.ts │ ├── schrono-utils.spec.ts │ ├── schrono-utils.ts │ ├── simple-duration.spec.ts │ ├── simple-duration.ts │ ├── simple-schedule.spec.ts │ └── simple-schedule.ts │ ├── string-utils.spec.ts │ ├── string-utils.ts │ ├── type-utils.ts │ ├── url-utils.spec.ts │ ├── url-utils.ts │ ├── zod-function-utils.ts │ ├── zod-jsonschema-utils.ts │ ├── zod-trpc-utils.ts │ └── zod-utils.ts ├── patches ├── @lilyrose2798__trpc-openapi@1.3.10.patch ├── @nangohq__frontend@0.33.8.patch ├── @stoplight__elements-core@7.7.10.patch ├── cac@6.7.12.patch ├── esbuild-jest@0.5.0.patch ├── firebase@9.8.1.patch ├── micro-memoize@4.0.10.patch └── typescript@4.8.2.patch ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── prettier.config.js ├── tsconfig.base.json ├── tsconfig.json ├── turbo.json ├── utils ├── env │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── openapi-client │ ├── .npmignore │ ├── index.ts │ ├── package.json │ ├── src │ │ ├── HTTPError.ts │ │ ├── createClient.ts │ │ ├── createOauthClient.ts │ │ └── index.ts │ └── tsconfig.json ├── types │ ├── PathsOf.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json └── zod │ ├── index.spec.ts │ ├── index.ts │ ├── package.json │ └── tsconfig.json └── verticals ├── vertical-accounting ├── accounting.ts ├── index.ts └── package.json ├── vertical-banking ├── adapters │ ├── qbo-adapter.ts │ └── xero-adapter.ts ├── banking.ts ├── index.ts └── package.json ├── vertical-investment ├── index.ts ├── investment.ts └── package.json ├── vertical-pta ├── index.ts ├── package.json ├── pta-types.ts └── pta-utils.ts └── vertical-sales-engagement ├── adapters ├── apollo-adapter.ts ├── outreach-adapter.ts └── salesloft-adapter.ts ├── index.ts ├── package.json ├── sales-engagement.ts └── schemas.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.patch] 15 | charset = unset 16 | end_of_line = unset 17 | indent_size = unset 18 | indent_style = unset 19 | insert_final_newline = unset 20 | trim_trailing_whitespace = unset 21 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Unignore dotfiles 2 | !.* 3 | 4 | # dependencies 5 | **/node_modules/ 6 | 7 | # temporary files 8 | **/temp/ 9 | 10 | # generated files 11 | **/__generated__/ 12 | *.generated.* 13 | *.gen.* 14 | *.oas.* 15 | 16 | # jest 17 | *.snap 18 | 19 | # next.js 20 | /apps/web/.next/ 21 | /apps/web/out/ 22 | 23 | # vim: set filetype=ignore: 24 | .obsidian/ 25 | 26 | docs/venice.oas.json 27 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | **/__generated__/ linguist-generated=true 2 | **/*.generated.* linguist-generated=true 3 | **/*.gen.* linguist-generated=true 4 | **/*.openapi.* linguist-generated=true 5 | **/*.oas.* linguist-generated=true 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | **/node_modules 5 | **/.pnp 6 | **/.pnp.js 7 | 8 | # testing 9 | /coverage 10 | /apps/tests 11 | 12 | # next.js 13 | /apps/web/.next/ 14 | /apps/web/out/ 15 | 16 | # production 17 | /apps/web/build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | .pnpm-debug.log* 28 | 29 | # local env files except example 30 | .env* 31 | !.env.example 32 | 33 | # symlinked for working with veniceFS 34 | /data 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | 42 | # eslint 43 | .eslintcache 44 | 45 | # tailwind 46 | /apps/web/__generated__/tailwind.css 47 | 48 | *.secret.json 49 | 50 | temp/ 51 | # We version control json files instead of the yaml ones 52 | *.oas.yaml 53 | .turbo 54 | dist/ 55 | 56 | *.play.* 57 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "apps/tests"] 2 | path = apps/tests 3 | url = git@github.com:alkafinance/ledger-sync-tests.git 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | pnpm run typecheck -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | tsup.config.ts 2 | tsconfig.json 3 | .turbo 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | public-hoist-pattern[]=@jest/types 2 | public-hoist-pattern[]=@trpc/server 3 | public-hoist-pattern[]=*babel* 4 | public-hoist-pattern[]=*eslint* 5 | public-hoist-pattern[]=cac 6 | public-hoist-pattern[]=chrono-node 7 | public-hoist-pattern[]=firebase 8 | public-hoist-pattern[]=micro-memoize 9 | public-hoist-pattern[]=next 10 | public-hoist-pattern[]=plaid 11 | public-hoist-pattern[]=remeda 12 | public-hoist-pattern[]=zod 13 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | **/node_modules/ 3 | 4 | # temporary files 5 | **/temp/ 6 | 7 | # generated files 8 | **/__generated__/ 9 | *.generated.* 10 | *.gen.* 11 | # *.oas.* 12 | 13 | # jest 14 | *.snap 15 | 16 | # next.js 17 | /apps/web/.next/ 18 | /apps/web/out/ 19 | 20 | # pnpm 21 | pnpm-lock.yaml 22 | 23 | # vim: set filetype=ignore: 24 | 25 | .obsidian/ 26 | 27 | docs/venice.oas.json 28 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "adpyke.vscode-sql-formatter", 4 | "bradlc.vscode-tailwindcss", 5 | "chrislajoie.vscode-modelines", 6 | "dbaeumer.vscode-eslint", 7 | "editorconfig.editorconfig", 8 | "esbenp.prettier-vscode", 9 | "fabiospampinato.vscode-highlight", 10 | "forbeslindesay.vscode-sql-template-literal", 11 | "maptz.regionfolder", 12 | "mikestead.dotenv", 13 | "naumovs.color-highlight", 14 | "orta.vscode-jest", 15 | "spywhere.mark-jump", 16 | "usernamehw.errorlens" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Run file", 11 | "runtimeArgs": ["--loader", "tsx"], 12 | "console": "integratedTerminal", 13 | "args": ["${file}"] 14 | }, 15 | { 16 | "type": "node", 17 | "request": "attach", 18 | "name": "Attach to --inspect-brk", 19 | "port": 9229 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting a Vulnerability 2 | 3 | >**Please do not post security vulnerabilities on our community Discord or file them as GitHub issues since those are both public audiences and could lead to additional security concerns.** 4 | 5 | Venice takes security issues very seriously. If you have any concerns about Venice or believe you have uncovered a vulnerability, contact us at security@venice.is. 6 | 7 | In the email, please try to describe the issue and a way to reproduce it. The security team will get back to you as soon as possible. 8 | 9 | 🙏 Please report any security problems to us before disclosing it publicly. 10 | -------------------------------------------------------------------------------- /apps/app-config/connectors/connectors.client.ts: -------------------------------------------------------------------------------- 1 | // generated by _generateConnectorLists.ts. Do not modify by hand 2 | import {default as connectorMerge} from '@usevenice/connector-merge/client' 3 | import {default as connectorOnebrick} from '@usevenice/connector-onebrick/client' 4 | import {default as connectorPlaid} from '@usevenice/connector-plaid/client' 5 | import {default as connectorTeller} from '@usevenice/connector-teller/client' 6 | import {default as connectorYodlee} from '@usevenice/connector-yodlee/client' 7 | 8 | export const clientConnectors = { 9 | merge: connectorMerge, 10 | onebrick: connectorOnebrick, 11 | plaid: connectorPlaid, 12 | teller: connectorTeller, 13 | yodlee: connectorYodlee, 14 | } 15 | -------------------------------------------------------------------------------- /apps/cli/README.md: -------------------------------------------------------------------------------- 1 | # Admin Query 2 | 3 | TablePlus -> Queries tab -> Right click -> New -> Add a shared folder to Queries 4 | 5 | This is how we persist common admin / debugging queries during development and share them with the team. 6 | -------------------------------------------------------------------------------- /apps/cli/airbyte-plaid-connector.ts: -------------------------------------------------------------------------------- 1 | import '@usevenice/app-config/register.node' 2 | 3 | import {plaidProvider} from '@usevenice/connector-plaid' 4 | import {makeAirbyteConnector} from '@usevenice/meta-service-airbyte/makeAirbyteConnector' 5 | 6 | import {cliFromRouter} from './cli-utils' 7 | 8 | cliFromRouter(makeAirbyteConnector(plaidProvider), { 9 | jsonOutput: true, 10 | consoleLog: false, 11 | readStdin: false, 12 | }).parse(process.argv) 13 | -------------------------------------------------------------------------------- /apps/cli/pgMigrator-cli.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tsx 2 | import '@usevenice/app-config/register.node' 3 | 4 | import path from 'node:path' 5 | 6 | import {makePostgresClient} from '@usevenice/connector-postgres' 7 | import {z} from '@usevenice/util' 8 | 9 | void makePostgresClient({ 10 | databaseUrl: z.string().parse(process.env['POSTGRES_OR_WEBHOOK_URL']), 11 | migrationsPath: path.join(__dirname, '../web/migrations'), 12 | migrationTableName: '_migrations', 13 | }).runMigratorCli() 14 | -------------------------------------------------------------------------------- /apps/gondola/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | .env 31 | 32 | # vercel 33 | .vercel 34 | 35 | # tailwind 36 | /__generated__/tailwind.css 37 | 38 | # Sentry 39 | .sentryclirc 40 | 41 | # Auto generated by next.js, but not used by us because we use monorepo 42 | .vscode 43 | -------------------------------------------------------------------------------- /apps/gondola/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import './global.css' 2 | 3 | import NextTopLoader from 'nextjs-toploader' 4 | 5 | export const metadata = { 6 | title: 'Gondola, your financial DB', 7 | // icons: [{url: '/favicon.svg', type: 'image/svg+xml'}], 8 | } 9 | 10 | export default function RootLayout({children}: {children: React.ReactNode}) { 11 | return ( 12 | 13 | 14 | 15 | 16 | {children} 17 | 18 | 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /apps/gondola/app/page.tsx: -------------------------------------------------------------------------------- 1 | export default function Home() { 2 | return ( 3 |
4 |

Hello Gondola

5 |
6 | ) 7 | } 8 | -------------------------------------------------------------------------------- /apps/gondola/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /apps/gondola/next.config.js: -------------------------------------------------------------------------------- 1 | // See https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/228 2 | // @ts-ignore 3 | const jiti = require('jiti')(__filename) 4 | module.exports = jiti('./next.config.ts').default 5 | -------------------------------------------------------------------------------- /apps/gondola/next.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | 3 | import type {NextConfig} from 'next' 4 | 5 | const nextConfig: NextConfig = { 6 | transpilePackages: [ 7 | path.resolve(__dirname, '../../packages/ui'), 8 | path.resolve(__dirname, '../../packages/util'), 9 | path.resolve(__dirname, '../../packages/connect'), 10 | ], 11 | experimental: {typedRoutes: true}, 12 | reactStrictMode: true, 13 | rewrites: async () => ({ 14 | beforeFiles: [ 15 | {source: '/_posthog/:p*', destination: 'https://app.posthog.com/:p*'}, 16 | ], 17 | afterFiles: [], 18 | fallback: [], 19 | }), 20 | swcMinify: true, 21 | typescript: {ignoreBuildErrors: true}, 22 | eslint: {ignoreDuringBuilds: true}, 23 | images: {domains: ['img.clerk.com', 'images.clerk.dev']}, 24 | } 25 | 26 | export default nextConfig 27 | -------------------------------------------------------------------------------- /apps/gondola/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/gondola", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "Gondola is an app built on top of Venice", 6 | "scripts": { 7 | "build": "run-s build:*", 8 | "build:migration": "echo TODO_RUN_MIGRATIONS", 9 | "build:next": "next build", 10 | "dev": "next dev --turbo", 11 | "start": "next start" 12 | }, 13 | "dependencies": { 14 | "@usevenice/connect": "workspace:*", 15 | "@usevenice/ui": "workspace:*", 16 | "@usevenice/util": "workspace:*", 17 | "next": "14.0.2", 18 | "nextjs-toploader": "1.4.2", 19 | "react": "18.2.0", 20 | "react-dom": "18.2.0" 21 | }, 22 | "devDependencies": { 23 | "@types/react": "18.0.27", 24 | "@types/react-dom": "18.0.10", 25 | "autoprefixer": "*", 26 | "jiti": "*", 27 | "node-loader": "2.0.0", 28 | "postcss": "*", 29 | "tailwindcss": "3.3.2", 30 | "tailwindcss-animate": "^1.0.5", 31 | "tailwindcss-radix": "2.5.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /apps/gondola/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /apps/gondola/sentry.properties: -------------------------------------------------------------------------------- 1 | defaults.url=https://sentry.io/ 2 | defaults.org=usevenice 3 | defaults.project=gondola 4 | -------------------------------------------------------------------------------- /apps/gondola/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/strictest/tsconfig.json", 3 | "compilerOptions": { 4 | "target": "ES5", 5 | "lib": ["DOM", "DOM.Iterable", "ES2021"], 6 | "allowJs": true, 7 | "exactOptionalPropertyTypes": false, 8 | "importsNotUsedAsValues": "remove", 9 | "noEmit": true, 10 | "incremental": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "strictNullChecks": true, 17 | "plugins": [{"name": "next"}], 18 | "paths": { 19 | "@/*": ["./*"] 20 | } 21 | }, 22 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 23 | "exclude": ["node_modules"] 24 | } 25 | -------------------------------------------------------------------------------- /apps/web/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | .env 31 | 32 | # vercel 33 | .vercel 34 | 35 | # tailwind 36 | /__generated__/tailwind.css 37 | 38 | # Sentry 39 | .sentryclirc 40 | 41 | # Auto generated by next.js, but not used by us because we use monorepo 42 | .vscode 43 | -------------------------------------------------------------------------------- /apps/web/@types/node-http-proxy-json.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'node-http-proxy-json' { 2 | /** 3 | * Modify the response of json 4 | * @param res {Response} The http response 5 | * @param proxyRes {proxyRes|String} String: The http header content-encoding: gzip/deflate 6 | * @param callback {Function} Custom modified logic 7 | */ 8 | export default function modifyResponse( 9 | res: import('http').ServerResponse, 10 | proxyRes: unknown, 11 | callback: (json: T) => U | Promise, 12 | ): void 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/app/(admin)/(authenticated)/connector-configs/page.tsx: -------------------------------------------------------------------------------- 1 | // import {SuperHydrate} from '@/components/SuperHydrate' 2 | // import {createServerComponentHelpers} from '@/server/server-component-helpers' 3 | 4 | import ConnectorConfigsPage from './ConnectorConfigPage' 5 | 6 | export default ConnectorConfigsPage 7 | // export default async function ConnectorConfigsPageContainer() { 8 | // const {ssg, getDehydratedState} = await createServerComponentHelpers() 9 | 10 | // await Promise.all([ssg.adminListIntegrations.prefetch()]) 11 | 12 | // return ( 13 | // 14 | // 15 | // 16 | // ) 17 | // } 18 | -------------------------------------------------------------------------------- /apps/web/app/(admin)/(authenticated)/page.tsx: -------------------------------------------------------------------------------- 1 | import {redirect} from 'next/navigation' 2 | 3 | export default function HomePage() { 4 | return redirect('/connector-configs') 5 | // return ( 6 | //
7 | //

8 | // Coming soon 9 | //

10 | //

11 | // A dashboard is coming soon. In the meantime check out entities section 12 | // and magic link page 13 | //

14 | //
15 | // ) 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/app/(admin)/(authenticated)/resources/[resourceId]/playground/page.tsx: -------------------------------------------------------------------------------- 1 | import type {Id} from '@usevenice/cdk' 2 | 3 | import {contextFactory} from '@/../app-config/backendConfig' 4 | import {getOrCreateApikey} from '@/lib-server' 5 | import {serverComponentGetViewer} from '@/lib-server/server-component-helpers' 6 | 7 | import {PlaygroundPage} from './PlaygroundPage' 8 | 9 | export default async function PlaygroundPageServer({ 10 | params: {resourceId}, 11 | }: { 12 | params: {resourceId: Id['reso']} 13 | }) { 14 | const viewer = await serverComponentGetViewer() 15 | const apikey = await getOrCreateApikey(viewer) 16 | const ctx = contextFactory.fromViewer(viewer) 17 | 18 | const resource = await ctx.services.getResourceExpandedOrFail(resourceId) 19 | 20 | const oas = resource.connectorConfig.connector.metadata?.openapiSpec?.proxied 21 | 22 | if (!oas) { 23 | return ( 24 |
25 | {resource.connectorName} does not have OpenAPI spec 26 |
27 | ) 28 | } 29 | 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /apps/web/app/(admin)/(authenticated)/resources/[resourceId]/sql/page.tsx: -------------------------------------------------------------------------------- 1 | import type {Id} from '@usevenice/cdk' 2 | 3 | import {contextFactory} from '@/../app-config/backendConfig' 4 | import {getOrCreateApikey} from '@/lib-server' 5 | import {serverComponentGetViewer} from '@/lib-server/server-component-helpers' 6 | 7 | import {SqlPage} from './SqlPage' 8 | 9 | export default async function SqlPageServer({ 10 | params: {resourceId}, 11 | }: { 12 | params: {resourceId: Id['reso']} 13 | }) { 14 | const viewer = await serverComponentGetViewer() 15 | const apikey = await getOrCreateApikey(viewer) 16 | const ctx = contextFactory.fromViewer(viewer) 17 | 18 | const resource = await ctx.services.getResourceOrFail(resourceId) 19 | if (resource.connectorName !== 'postgres') { 20 | return ( 21 |
Only postgres resources are supported for sql
22 | ) 23 | } 24 | 25 | return 26 | } 27 | -------------------------------------------------------------------------------- /apps/web/app/(admin)/(authenticated)/resources/page.tsx: -------------------------------------------------------------------------------- 1 | // import {SuperHydrate} from '@/components/SuperHydrate' 2 | // import {createServerComponentHelpers} from '@/server/server-component-helpers' 3 | 4 | import ResourcePage from './ResourcesPage' 5 | export default ResourcePage 6 | 7 | // export default async function ResourcesPageContainer() { 8 | // const {ssg, getDehydratedState} = await createServerComponentHelpers() 9 | 10 | // await Promise.all([ 11 | // ssg.listIntegrationInfos.fetch({}), 12 | // ssg.listConnections.prefetch({}), 13 | // ]) 14 | 15 | // // Anyway to stream the preConnect response to client so client does not 16 | // // have to make a round-trip? We don't want to do it right away 17 | // // because we do not want to block the initial page load on 3rd party API endpoints 18 | // // await integrations.map( 19 | // // ssg.preConnect() 20 | // // ) 21 | 22 | // return ( 23 | // 24 | // 25 | // 26 | // ) 27 | // } 28 | -------------------------------------------------------------------------------- /apps/web/app/(admin)/(authenticated)/settings/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | export default function SettingsPage() { 4 | return ( 5 |
6 |

Settings

7 |

Under construction

8 |
9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /apps/web/app/(admin)/layout.tsx: -------------------------------------------------------------------------------- 1 | import {ClerkProvider} from '@clerk/nextjs' 2 | // import {TRPCProvider} from '@usevenice/engine-frontend' 3 | import React from 'react' 4 | 5 | import {ClientRootWithClerk} from '@/components/ClientRoot' 6 | 7 | export default function AdminLayout(props: {children: React.ReactNode}) { 8 | console.log('[AdminLayout] rendering') 9 | // We only get the viewer from cookies to be consistent with how it works 10 | // createBrowserSupabaseClient which only uses cookie and does not use header etc. 11 | 12 | return ( 13 | 14 | {props.children} 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /apps/web/app/(admin)/org/[slug]/page.tsx: -------------------------------------------------------------------------------- 1 | import {auth as serverComponentGetAuth} from '@clerk/nextjs' 2 | 3 | export default function OrgHomePage() { 4 | return ( 5 |
6 |

7 | You are logged in as 8 |

9 |
{JSON.stringify(serverComponentGetAuth(), null, 2)}
10 |
11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /apps/web/app/(admin)/sign-in/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import {SignIn} from '@clerk/nextjs' 4 | 5 | import {FullScreenCenter} from '@/components/FullScreenCenter' 6 | 7 | export default function SignInScreen() { 8 | return ( 9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/app/(admin)/sign-up/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import {SignUp} from '@clerk/nextjs' 4 | 5 | import {FullScreenCenter} from '@/components/FullScreenCenter' 6 | 7 | export default function SignInScreen() { 8 | return ( 9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/app/api/me/route.ts: -------------------------------------------------------------------------------- 1 | import type {NextRequest} from 'next/server' 2 | import {NextResponse} from 'next/server' 3 | 4 | import {withErrorHandler} from '@/lib-server' 5 | import {serverComponentGetViewer} from '@/lib-server/server-component-helpers' 6 | 7 | export async function GET(request: NextRequest) { 8 | return withErrorHandler(async () => { 9 | const viewer = await serverComponentGetViewer(request.nextUrl) 10 | return NextResponse.json(viewer) 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /apps/web/app/connect/ConnectPage.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import {clientConnectors} from '@usevenice/app-config/connectors/connectors.client' 4 | import type {VeniceConnectProps} from '@usevenice/engine-frontend' 5 | import {VeniceConnect} from '@usevenice/engine-frontend' 6 | 7 | /** 8 | * Only reason this file exists is because we cannot pass clientConnectors directly 9 | * from a server component because it contains function references (i.e. useConnectHook) 10 | */ 11 | export default function ConnectPage( 12 | props: Omit, 13 | ) { 14 | return ( 15 | 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /apps/web/app/connect/SetCookieAndRedirect.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import {setCookie} from 'cookies-next' 4 | import type {OptionsType} from 'cookies-next/lib/types' 5 | import React from 'react' 6 | 7 | /** 8 | * Workaround for inability to set cookie in server components 9 | * @see https://github.com/vercel/next.js/discussions/49843 10 | */ 11 | export function SetCookieAndRedirect(props: { 12 | cookies: Array<{key: string; value: string; options: OptionsType}> 13 | redirectUrl: string 14 | }) { 15 | React.useEffect(() => { 16 | for (const {key, value, options} of props.cookies) { 17 | setCookie(key, value, options) 18 | } 19 | 20 | // no need for NextRouter since we are doing a full page redirect 21 | window.location.href = props.redirectUrl 22 | 23 | // eslint-disable-next-line react-hooks/exhaustive-deps 24 | }, []) 25 | return null 26 | } 27 | -------------------------------------------------------------------------------- /apps/web/app/connect/callback/CallbackEffect.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import {Loader2} from 'lucide-react' 4 | import React from 'react' 5 | import type {FrameMessage} from '@usevenice/connect' 6 | 7 | export function CallbackEffect(props: { 8 | msg: FrameMessage | null 9 | autoClose?: boolean 10 | }) { 11 | const opener = ( 12 | typeof window !== 'undefined' ? window.opener : null 13 | ) as Window | null 14 | 15 | React.useEffect(() => { 16 | if (props.msg) { 17 | opener?.postMessage(props.msg, '*') 18 | } 19 | 20 | if (props.autoClose) { 21 | setTimeout(() => { 22 | window.close() 23 | }, 300) 24 | } 25 | // eslint-disable-next-line react-hooks/exhaustive-deps 26 | }, []) 27 | 28 | return opener ? : null 29 | } 30 | -------------------------------------------------------------------------------- /apps/web/app/demo/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import 'next/image' 4 | import '../global.css' 5 | 6 | import {useSearchParams} from 'next/navigation' 7 | 8 | import {VeniceConnectEmbed} from '@usevenice/connect' 9 | 10 | export default function Demo() { 11 | const params = useSearchParams() 12 | const token = params?.get('token') 13 | return ( 14 |
15 | {token ? ( 16 | 17 | ) : ( 18 |

19 | Please pass a valid venice connect token in the url as query param 20 | `?token=` 21 |

22 | )} 23 |
24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /apps/web/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import './global.css' 2 | 3 | import {env} from '@usevenice/app-config/env' 4 | 5 | export const metadata = { 6 | title: `${ 7 | env.VERCEL_ENV === 'production' ? '' : `[${env.VERCEL_ENV}] ` 8 | }Venice — Financial data, fast.`, 9 | icons: [{url: '/favicon.svg', type: 'image/svg+xml'}], 10 | } 11 | 12 | export default function RootLayout({children}: {children: React.ReactNode}) { 13 | return ( 14 | 15 | 16 | {children} 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /apps/web/components/FullScreenCenter.tsx: -------------------------------------------------------------------------------- 1 | export function FullScreenCenter(props: {children: React.ReactNode}) { 2 | return ( 3 |
4 | {props.children} 5 |
6 | ) 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/components/NoSSR.tsx: -------------------------------------------------------------------------------- 1 | import dynamic from 'next/dynamic' 2 | import React from 'react' 3 | 4 | const _NoSSR = (props: {children: React.ReactNode}) => ( 5 | {props.children} 6 | ) 7 | 8 | export const NoSSR = dynamic(() => Promise.resolve(_NoSSR), { 9 | ssr: false, 10 | }) 11 | -------------------------------------------------------------------------------- /apps/web/components/RedirectTo.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import {useRouter} from 'next/navigation' 4 | import {useEffect} from 'react' 5 | 6 | export function RedirectToNext13(props: { 7 | url: string 8 | children?: React.ReactNode 9 | }) { 10 | const router = useRouter() 11 | // Only trigger once... 12 | useEffect(() => { 13 | // eslint-disable-next-line @typescript-eslint/no-unsafe-argument 14 | router.push(props.url as any) 15 | // eslint-disable-next-line react-hooks/exhaustive-deps 16 | }, []) 17 | 18 | return <>{props.children} 19 | } 20 | -------------------------------------------------------------------------------- /apps/web/components/SuperHydrate.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import {Hydrate} from '@tanstack/react-query' 4 | import React from 'react' 5 | import superjson from 'superjson' 6 | import type {SuperJSONResult} from 'superjson/dist/types' 7 | 8 | export type DehydratedState = SuperJSONResult 9 | 10 | /** 11 | * Hydrate using superjson 12 | * TODO: Figure out if we can use SuperHydrate multiple times for different parts of the app 13 | * or if it can only be called once for the entire app's state without ability to merge them together 14 | */ 15 | export function SuperHydrate(props: { 16 | dehydratedState?: DehydratedState 17 | children: React.ReactNode 18 | }) { 19 | return ( 20 | 24 | {props.children} 25 | 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /apps/web/lib-client/copyToClipboard.ts: -------------------------------------------------------------------------------- 1 | export async function copyToClipboard(content: string) { 2 | console.debug('Will save to clipboard', content) 3 | 4 | // Workaround https://stackoverflow.com/questions/51805395/navigator-clipboard-is-undefined 5 | if (typeof navigator.clipboard === 'undefined') { 6 | console.debug('Will use textarea hack to copy text') 7 | const textarea = document.createElement('textarea') 8 | textarea.value = content 9 | textarea.style.position = 'fixed' // avoid scrolling to bottom 10 | document.body.append(textarea) 11 | textarea.focus() 12 | textarea.select() 13 | try { 14 | document.execCommand('copy') 15 | } catch { 16 | console.warn('Unable to use textarea hack to copy') 17 | } 18 | textarea.remove() 19 | } else { 20 | await navigator.clipboard.writeText(content) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /apps/web/lib-client/trpcReact.ts: -------------------------------------------------------------------------------- 1 | import type {TRPCReact} from '@usevenice/engine-frontend' 2 | import {_trpcReact} from '@usevenice/engine-frontend' 3 | 4 | import type {AppRouter} from '../lib-server/appRouter' 5 | 6 | /** Move this somewhere where other components can access */ 7 | export const trpcReact = _trpcReact as unknown as TRPCReact 8 | -------------------------------------------------------------------------------- /apps/web/lib-client/ui-utils.ts: -------------------------------------------------------------------------------- 1 | export {cn} from '@usevenice/ui/utils' 2 | -------------------------------------------------------------------------------- /apps/web/lib-server/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './procedures' 3 | export * from './server-helpers' 4 | // codegen:end 5 | -------------------------------------------------------------------------------- /apps/web/lib-server/server-component-helpers.ts: -------------------------------------------------------------------------------- 1 | import {cookies} from 'next/headers' 2 | 3 | import type {kAccessToken} from '@usevenice/app-config/constants' 4 | 5 | import {createSSRHelpers, serverGetViewer} from './server-helpers' 6 | 7 | export function createServerComponentHelpers(opts?: { 8 | searchParams: {[kAccessToken]?: string | string[]} | URLSearchParams 9 | }) { 10 | return createSSRHelpers({cookies, searchParams: opts?.searchParams}) 11 | } 12 | 13 | /** Used in router handler actually, not just server component */ 14 | export function serverComponentGetViewer(opts?: { 15 | searchParams: {[kAccessToken]?: string | string[]} | URLSearchParams 16 | }) { 17 | return serverGetViewer({cookies, searchParams: opts?.searchParams}) 18 | } 19 | -------------------------------------------------------------------------------- /apps/web/middleware.ts: -------------------------------------------------------------------------------- 1 | import {authMiddleware} from '@clerk/nextjs' 2 | 3 | // Disable redirects 4 | export default authMiddleware({publicRoutes: [/^(.*)/]}) 5 | 6 | export const config = { 7 | /* 8 | * Match all request paths except for the ones starting with: 9 | * - _next 10 | * - static (static files) 11 | * - favicon.ico (favicon file) 12 | * - public folder 13 | * - public folder 14 | * - connect (Venice connect, oauth, which has separate auth logic) 15 | * - debug page 16 | */ 17 | matcher: [ 18 | '/((?!.*\\..*|_next|connect|debug).*)', 19 | '/', 20 | '/(api|trpc|connector)(.*)', 21 | ], 22 | } 23 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-01-25_rename_to_raw.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE "public"."transaction" RENAME TO "raw_transaction"; 2 | ALTER TABLE "public"."account" RENAME TO "raw_account"; 3 | ALTER TABLE "public"."commodity" RENAME TO "raw_commodity"; 4 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-02-01_user_apikey_index.sql: -------------------------------------------------------------------------------- 1 | DO $$ 2 | BEGIN 3 | IF (SELECT to_regclass('auth.users') IS NOT null) 4 | THEN 5 | CREATE INDEX IF NOT EXISTS users_api_key 6 | ON "auth"."users" ((raw_app_meta_data ->> 'apiKey')); 7 | END IF; 8 | END $$ 9 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-02-02_add_connection_name.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE "public"."resource" ADD COLUMN "display_name" varchar; 2 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-02-03_graphql_comments.sql: -------------------------------------------------------------------------------- 1 | -- @see https://github.com/supabase/pg_graphql/issues/167 2 | comment on constraint fk_source_id 3 | on "pipeline" 4 | is E'@graphql({"foreign_name": "source", "local_name": "sourceOfPipelines"})'; 5 | 6 | comment on constraint fk_destination_id 7 | on "pipeline" 8 | is E'@graphql({"foreign_name": "destination", "local_name": "destinationOfPipelines"})'; 9 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-02-22_institution_rls.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE OR REPLACE FUNCTION auth.institution_ids() 3 | RETURNS character varying[] 4 | LANGUAGE sql 5 | STABLE 6 | AS $function$ 7 | select array( 8 | SELECT DISTINCT institution_id FROM "resource" 9 | WHERE creator_id = public._uid () AND institution_id IS NOT NULL 10 | ) 11 | $function$; 12 | 13 | DROP POLICY IF EXISTS "public_readable" on "public"."institution"; 14 | DROP POLICY IF EXISTS "connection_creator_access" on "public"."institution"; 15 | CREATE POLICY "connection_creator_access" ON "public"."institution" 16 | USING ("id" = ANY(auth.institution_ids())) 17 | WITH CHECK ("id" = ANY(auth.institution_ids())); 18 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-02-27_revoke_anon.sql: -------------------------------------------------------------------------------- 1 | 2 | -- TODO: Use the supabase image rather than postgres image for testing in ci 3 | DO 4 | $do$ 5 | BEGIN 6 | -- Surround in a check so that this migration does not fail in a vanilla postgres instance 7 | IF NOT EXISTS ( 8 | SELECT FROM pg_catalog.pg_roles 9 | WHERE rolname = 'anon') THEN 10 | RAISE NOTICE 'Role "anon" does not exists. Skipping grant.'; 11 | ELSE 12 | REVOKE ALL PRIVILEGES ON public._migrations from anon, authenticated; 13 | END IF; 14 | END 15 | $do$; 16 | 17 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-02-28_1307_enable_realtime_publications.sql: -------------------------------------------------------------------------------- 1 | -- https://supabase.com/docs/guides/realtime/quickstart 2 | -- https://supabase.com/docs/guides/auth/row-level-security#enable-realtime-for-database-tables 3 | 4 | BEGIN; 5 | DROP publication IF EXISTS supabase_realtime; 6 | CREATE publication supabase_realtime; 7 | ALTER publication supabase_realtime ADD TABLE integration, resource, pipeline, institution; 8 | COMMIT; 9 | 10 | -- ALTER publication supabase_realtime DROP TABLE integration, resource, pipeline, institution; 11 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-02-28_1954_remove_public_uid.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION auth.uid() 2 | RETURNS varchar 3 | LANGUAGE sql 4 | STABLE 5 | AS $function$ 6 | select coalesce( 7 | nullif(current_setting('request.jwt.claim.sub', true), ''), 8 | (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub') 9 | ) 10 | $function$; 11 | 12 | 13 | CREATE OR REPLACE FUNCTION auth.resource_ids() 14 | RETURNS character varying[] 15 | LANGUAGE sql 16 | STABLE 17 | AS $function$ 18 | select array(select id from "resource" where creator_id = auth.uid()) 19 | $function$; 20 | 21 | CREATE OR REPLACE FUNCTION auth.institution_ids() 22 | RETURNS character varying[] 23 | LANGUAGE sql 24 | STABLE 25 | AS $function$ 26 | select array( 27 | SELECT DISTINCT institution_id FROM "resource" 28 | WHERE creator_id = auth.uid() AND institution_id IS NOT NULL 29 | ) 30 | $function$; 31 | 32 | -- This workaround is no longer needed now that user are not logging in directly anhmore. 33 | DROP FUNCTION IF EXISTS public._uid(); 34 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-10-23_0313_integration_env_name.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE integration ADD COLUMN env_name varchar 2 | GENERATED ALWAYS AS (config ->> 'envName') STORED; 3 | 4 | GRANT SELECT(env_name, display_name) ON TABLE public.integration TO end_user; 5 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-10-29_2125_integration_provider_name_grant.sql: -------------------------------------------------------------------------------- 1 | GRANT SELECT(provider_name) ON TABLE public.integration TO end_user; 2 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-11-14_0109_pipeline_disabled.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE pipeline ADD disabled BOOLEAN DEFAULT FALSE; 2 | ALTER TABLE resource ADD disabled BOOLEAN DEFAULT FALSE; 3 | ALTER TABLE integration ADD disabled BOOLEAN DEFAULT FALSE; 4 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-11-20_1923_connector_name.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE institution RENAME COLUMN provider_name TO connector_name; 2 | ALTER TABLE integration RENAME COLUMN provider_name TO connector_name; 3 | ALTER TABLE resource RENAME COLUMN provider_name TO connector_name; 4 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-11-21_0821_integration_to_connector_config.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Unrelated 3 | 4 | ALTER TABLE resource DROP CONSTRAINT fk_institution_id; 5 | ALTER TABLE resource 6 | ADD CONSTRAINT "fk_institution_id" FOREIGN KEY ("institution_id") 7 | REFERENCES "public"."institution"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 8 | 9 | -- Drop constraints rename and re-add constraints 10 | 11 | ALTER TABLE resource DROP CONSTRAINT fk_integration_id; 12 | ALTER TABLE integration DROP CONSTRAINT integration_id_prefix_check; 13 | 14 | ALTER TABLE integration RENAME TO connector_config; 15 | ALTER TABLE resource RENAME COLUMN integration_id TO connector_config_id; 16 | 17 | ALTER TABLE resource 18 | ADD CONSTRAINT "fk_connector_config_id" FOREIGN KEY ("connector_config_id") 19 | REFERENCES "public"."connector_config"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 20 | 21 | UPDATE connector_config set id = REPLACE(id, 'int_', 'ccfg_'); 22 | ALTER TABLE connector_config 23 | ALTER COLUMN id SET DEFAULT concat('ccfg_', public.generate_ulid()), 24 | ADD CONSTRAINT connector_config_id_prefix_check CHECK (starts_with(id, 'ccfg_')); 25 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-11-21_0934_institution_to_integration.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE resource DROP CONSTRAINT fk_institution_id; 2 | ALTER TABLE institution DROP CONSTRAINT institution_id_prefix_check; 3 | 4 | ALTER TABLE institution RENAME TO integration; 5 | ALTER TABLE resource RENAME COLUMN institution_id TO integration_id; 6 | 7 | ALTER TABLE resource 8 | ADD CONSTRAINT "fk_integration_id" FOREIGN KEY ("integration_id") 9 | REFERENCES "public"."integration"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 10 | 11 | UPDATE integration set id = CONCAT('int_', SUBSTRING(id, LENGTH('ins_') + 1)); 12 | ALTER TABLE integration 13 | ALTER COLUMN id SET DEFAULT concat('int_', public.generate_ulid()), 14 | ADD CONSTRAINT integration_id_prefix_check CHECK (starts_with(id, 'int_')); 15 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-11-24_0008_connector_config_src_dest.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE connector_config ADD COLUMN default_destination_id varchar 2 | GENERATED ALWAYS AS (config ->> 'default_destination_id') STORED; 3 | ALTER TABLE connector_config 4 | ADD CONSTRAINT "fk_default_destination_id" FOREIGN KEY ("default_destination_id") 5 | REFERENCES "public"."resource"("id") ON DELETE RESTRICT ON UPDATE RESTRICT; 6 | 7 | ALTER TABLE connector_config ADD COLUMN default_source_id varchar 8 | GENERATED ALWAYS AS (config ->> 'default_source_id') STORED; 9 | ALTER TABLE connector_config 10 | ADD CONSTRAINT "fk_default_source_id" FOREIGN KEY ("default_source_id") 11 | REFERENCES "public"."resource"("id") ON DELETE RESTRICT ON UPDATE RESTRICT; 12 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-11-25_0545_connector_config_src_dest_top_level.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE connector_config DROP CONSTRAINT "fk_default_source_id"; 2 | ALTER TABLE connector_config DROP CONSTRAINT "fk_default_destination_id"; 3 | ALTER TABLE connector_config DROP COLUMN default_source_id; 4 | ALTER TABLE connector_config DROP COLUMN default_destination_id; 5 | 6 | ALTER TABLE connector_config ADD COLUMN default_destination_id varchar; 7 | ALTER TABLE connector_config 8 | ADD CONSTRAINT "fk_default_destination_id" FOREIGN KEY ("default_destination_id") 9 | REFERENCES "public"."resource"("id") ON DELETE SET NULL ON UPDATE CASCADE; 10 | 11 | ALTER TABLE connector_config ADD COLUMN default_source_id varchar; 12 | ALTER TABLE connector_config 13 | ADD CONSTRAINT "fk_default_source_id" FOREIGN KEY ("default_source_id") 14 | REFERENCES "public"."resource"("id") ON DELETE SET NULL ON UPDATE CASCADE; 15 | 16 | 17 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-11-30_2212_add_metadata.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE connector_config ADD COLUMN metadata jsonb; 2 | ALTER TABLE resource ADD COLUMN metadata jsonb; 3 | ALTER TABLE pipeline ADD COLUMN metadata jsonb; 4 | -------------------------------------------------------------------------------- /apps/web/migrations/2023-11-30_2310_drop_end_user_access.sql: -------------------------------------------------------------------------------- 1 | DROP POLICY IF EXISTS end_user_access ON public.connector_config; 2 | CREATE POLICY end_user_access ON public.connector_config TO end_user 3 | USING (org_id = jwt_org_id()); 4 | 5 | ALTER TABLE connector_config DROP COLUMN end_user_access; 6 | -------------------------------------------------------------------------------- /apps/web/migrations_wip/2023-01-06_connection-user.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Supabase specific now -- 3 | 4 | -- How do we ensure connections are deleted with their corresponding users are deleted? 5 | 6 | CREATE TABLE IF NOT EXISTS "public"."connection_user" ( 7 | "connection_id" varchar NOT NULL, 8 | "user_id" varchar NOT NULL, 9 | -- "permission" -- To be added later 10 | CONSTRAINT "fk_connection_id" FOREIGN KEY ("connection_id") 11 | REFERENCES "public"."connection"("id") ON DELETE CASCADE, 12 | CONSTRAINT "fk_user_id" FOREIGN KEY ("user_id") 13 | REFERENCES "auth"."users"("id") ON DELETE CASCADE, 14 | ) 15 | -------------------------------------------------------------------------------- /apps/web/migrations_wip/2023-02-27_2252_postgres-follow-privileges.sql: -------------------------------------------------------------------------------- 1 | -- Workaround the issue where public.migrations table show up for anonymous users... 2 | -- @see https://usevenice.slack.com/archives/C04NUANB7FW/p1677504283755269?thread_ts=1677488220.098729&cid=C04NUANB7FW 3 | 4 | -- Must run from supabase sql dashboard otherwise will get the following error 5 | -- Query 1 ERROR: ERROR: "authenticator" is a reserved role, only superusers can modify it 6 | 7 | -- [x] venice-dev 8 | -- [x] venice-staging 9 | -- [x] venice-production 10 | 11 | ALTER ROLE authenticator SET pgrst.openapi_mode TO 'follow-privileges'; 12 | NOTIFY pgrst, 'reload config'; 13 | -------------------------------------------------------------------------------- /apps/web/migrations_wip/2023-04-22_1501_pre_request_to_mcte.sql: -------------------------------------------------------------------------------- 1 | -- @see https://github.com/orgs/supabase/discussions/9311#discussioncomment-5690939 2 | -- Should be more scalable than the previous approach, which was to use pre-request hooks 3 | -- for postgrest but it does not work for things like postgres-realtime, nor does it work in 4 | -- non-postgrest environments such as non-supabase-postgres or any kind of direct user login 5 | -------------------------------------------------------------------------------- /apps/web/migrations_wip/2023-04-22_2039_end_user_table.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Checklist: 3 | - [ ] Add a table of end users 4 | - [ ] Scoping end user id to workspace id 5 | */ 6 | 7 | -- CREATE TABLE IF NOT EXISTS "public"."end_user" ( 8 | -- "id" character varying NOT NULL DEFAULT generate_ulid(), 9 | -- "provider_name" character varying NOT NULL GENERATED ALWAYS AS (split_part(id, '_', 2)) STORED, 10 | -- -- "standard" jsonb NOT NULL DEFAULT '{}', What should it be? 11 | -- "config" jsonb NOT NULL DEFAULT '{}', 12 | -- "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), 13 | -- "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), 14 | -- CONSTRAINT "pk_end_user" PRIMARY KEY ("id") 15 | -- ); 16 | -- ALTER TABLE "public"."connection" ENABLE ROW LEVEL SECURITY; 17 | -- CREATE INDEX IF NOT EXISTS integration_created_at ON integration (created_at); 18 | -- CREATE INDEX IF NOT EXISTS integration_updated_at ON integration (updated_at); 19 | -- CREATE INDEX IF NOT EXISTS integration_provider_name ON integration (provider_name); 20 | -------------------------------------------------------------------------------- /apps/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | // NOTE: This file should not be edited 6 | // see https://nextjs.org/docs/basic-features/typescript for more information. 7 | -------------------------------------------------------------------------------- /apps/web/pages/api/debug.ts: -------------------------------------------------------------------------------- 1 | import type {NextApiHandler} from 'next' 2 | 3 | export default ((_req, res) => { 4 | console.log('req.query', _req.query) 5 | res.send({ok: true}) 6 | }) satisfies NextApiHandler 7 | -------------------------------------------------------------------------------- /apps/web/pages/api/graphql/[[...graphql]].ts: -------------------------------------------------------------------------------- 1 | import '@usevenice/app-config/register.node' 2 | import {joinPath} from '@usevenice/util' 3 | 4 | import type {NextApiHandler} from 'next' 5 | import {serverAnalytics} from '../../../lib-server/analytics-server' 6 | 7 | import {proxySupabase} from '../../../lib-server/supabase-proxy' 8 | 9 | // Enable `externalResolver` option in Next.js 10 | export const config = { 11 | api: {externalResolver: true, bodyParser: false}, 12 | } 13 | 14 | export default (async (req, res) => 15 | proxySupabase({ 16 | req, 17 | res, 18 | targetPath: joinPath('graphql/v1', req.url?.replace('/api/graphql', '')), 19 | onUserId: (userId) => { 20 | if (userId) { 21 | serverAnalytics.track(userId, {name: 'api/graphql-request', data: {}}) 22 | } 23 | return serverAnalytics.flush({ignoreErrors: true}) 24 | }, 25 | })) satisfies NextApiHandler 26 | -------------------------------------------------------------------------------- /apps/web/pages/api/sentry_sample_error.ts: -------------------------------------------------------------------------------- 1 | import type {NextApiHandler} from 'next' 2 | 3 | import {serverAnalytics} from '../../lib-server/analytics-server' 4 | 5 | // true 6 | export default (async (_req, _res) => { 7 | serverAnalytics.track('test', {name: 'debug/debug', data: {}}) 8 | await serverAnalytics.flush() 9 | throw new Error('Sentry Backend Error') 10 | }) satisfies NextApiHandler 11 | -------------------------------------------------------------------------------- /apps/web/pages/api/trpc/index.ts: -------------------------------------------------------------------------------- 1 | import type {NextApiRequest, NextApiResponse} from 'next' 2 | import {renderTrpcPanel} from 'trpc-panel' 3 | import {appRouter} from '@/lib-server/appRouter' 4 | 5 | export default function handler(req: NextApiRequest, res: NextApiResponse) { 6 | // req.url is normally `/api/trpc` already which is the right place 7 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion 8 | res.status(200).send(renderTrpcPanel(appRouter, {url: req.url!})) 9 | } 10 | -------------------------------------------------------------------------------- /apps/web/pages/api/v0/[...trpc].ts: -------------------------------------------------------------------------------- 1 | import {createOpenApiNextHandler} from '@lilyrose2798/trpc-openapi' 2 | import {respondToCORS} from '@/lib-server' 3 | import {appRouter} from '@/lib-server/appRouter' 4 | import '@usevenice/app-config/register.node' 5 | import type {NextApiHandler} from 'next' 6 | import {createContext, onError} from '../trpc/[...trpc]' 7 | 8 | const handler = createOpenApiNextHandler({ 9 | // not sure why this cast is needed... 10 | router: appRouter as any, 11 | createContext, 12 | onError, 13 | }) 14 | 15 | export default (function trpcOpenAPIHandler(req, res) { 16 | if (respondToCORS(req, res)) { 17 | return 18 | } 19 | if (req.headers['transfer-encoding'] === 'chunked') { 20 | res.status(400).send('Chunked transfer encoding is not supported') 21 | return 22 | } 23 | console.log( 24 | '[trpcOpenAPIHandler]', 25 | req.url, 26 | req.method, 27 | // req.headers, 28 | // req.body, 29 | ) 30 | 31 | return handler(req, res) 32 | } satisfies NextApiHandler) 33 | -------------------------------------------------------------------------------- /apps/web/pages/api/v0/index.ts: -------------------------------------------------------------------------------- 1 | import type {NextApiRequest, NextApiResponse} from 'next' 2 | 3 | export default function handler(_: NextApiRequest, res: NextApiResponse) { 4 | // https://github.com/stoplightio/elements 5 | res.status(200).send(` 6 | 7 | 8 | 9 | 10 | 11 | Elements in HTML 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | `) 27 | } 28 | -------------------------------------------------------------------------------- /apps/web/pages/api/webhook/[[...webhook]].ts: -------------------------------------------------------------------------------- 1 | import '@usevenice/app-config/register.node' 2 | import type {NextApiHandler} from 'next' 3 | import {inngest} from '@usevenice/engine-backend' 4 | import {fromMaybeArray, makeUlid} from '@usevenice/util' 5 | 6 | export default (async (req, res) => { 7 | const {webhook, ...query} = req.query 8 | // Workaround for lack of response from inngest.send https://discord.com/channels/842170679536517141/845000011040555018/1080057253060694036 9 | const traceId = makeUlid() 10 | // TODO: Figure out a way to handle webhook within current request to help with debugging 11 | // Or at least validating the request for things like HMAC signature and payload formatting 12 | await inngest.send({ 13 | name: 'webhook/received', 14 | data: { 15 | traceId, 16 | method: req.method ?? '', 17 | headers: req.headers ?? {}, 18 | path: fromMaybeArray(webhook ?? '').join('/'), 19 | query, 20 | body: req.body, 21 | }, 22 | }) 23 | res.send({status: 'queued', traceId}) 24 | }) satisfies NextApiHandler 25 | -------------------------------------------------------------------------------- /apps/web/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-airtable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-airtable.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-brex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-brex.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-firebase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-firebase.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-heron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-heron.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-import.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-mercury.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-mercury.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-mongodb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-mongodb.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-moota.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-moota.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-onebrick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-onebrick.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-postgres.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-postgres.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-ramp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-ramp.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-saltedge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-saltedge.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-spreadsheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-spreadsheet.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-stripe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-stripe.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-venmo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-venmo.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-webhook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-webhook.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-wise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-wise.png -------------------------------------------------------------------------------- /apps/web/public/_assets/logo-yodlee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/_assets/logo-yodlee.png -------------------------------------------------------------------------------- /apps/web/public/copy-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /apps/web/public/db-links-line.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/web/public/fidelity-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/web/public/heron-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/heron-logo.png -------------------------------------------------------------------------------- /apps/web/public/institution-placeholder.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/web/public/mergeLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/mergeLogo.png -------------------------------------------------------------------------------- /apps/web/public/netsuiteLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/netsuiteLogo.png -------------------------------------------------------------------------------- /apps/web/public/pipeline-in.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/web/public/pipeline-out.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/web/public/plaidLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/plaidLogo.png -------------------------------------------------------------------------------- /apps/web/public/qboLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/qboLogo.png -------------------------------------------------------------------------------- /apps/web/public/requestLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/requestLogo.png -------------------------------------------------------------------------------- /apps/web/public/stripeLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/stripeLogo.png -------------------------------------------------------------------------------- /apps/web/public/venice-database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/public/venice-database.png -------------------------------------------------------------------------------- /apps/web/sentry.edge.config.ts: -------------------------------------------------------------------------------- 1 | import './sentry.server.config' 2 | -------------------------------------------------------------------------------- /apps/web/sentry.properties: -------------------------------------------------------------------------------- 1 | defaults.url=https://sentry.io/ 2 | defaults.org=usevenice 3 | defaults.project=venice 4 | -------------------------------------------------------------------------------- /apps/web/supabase/.gitignore: -------------------------------------------------------------------------------- 1 | # Supabase 2 | .branches 3 | .temp 4 | -------------------------------------------------------------------------------- /apps/web/supabase/seed.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/apps/web/supabase/seed.sql -------------------------------------------------------------------------------- /apps/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/strictest/tsconfig.json", 3 | "compilerOptions": { 4 | "target": "ES5", 5 | "lib": ["DOM", "DOM.Iterable", "ES2021"], 6 | "allowJs": true, 7 | "exactOptionalPropertyTypes": false, 8 | "importsNotUsedAsValues": "remove", 9 | "noEmit": true, 10 | "incremental": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "strictNullChecks": true, 17 | "plugins": [{"name": "next"}], 18 | "paths": {"@/*": ["./*"]} 19 | }, 20 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 21 | "exclude": ["node_modules"] 22 | } 23 | -------------------------------------------------------------------------------- /bin/venice.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tsx 2 | // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call 3 | require('@usevenice/cli/venice-cli').default.help().parse() 4 | -------------------------------------------------------------------------------- /connectors/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /connectors/README.md: -------------------------------------------------------------------------------- 1 | ```dataview 2 | TABLE WITHOUT ID 3 | link(file.path, replace(replace(file.path, "/README.md", ""), "connectorss/connectors-", "") 4 | ) as connectors, 5 | status as Status 6 | FROM "connectorss" 7 | WHERE file.path != "connectorss/README.md" 8 | ``` 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /connectors/connector-airtable/def.ts: -------------------------------------------------------------------------------- 1 | import type {ConnectorDef, ConnectorSchemas} from '@usevenice/cdk' 2 | import {connHelpers} from '@usevenice/cdk' 3 | import type {EntityPayloadWithRaw} from '@usevenice/cdk' 4 | import {z, zCast} from '@usevenice/util' 5 | 6 | import {zAirtableResourceSettings} from './AirtableClient' 7 | 8 | export const airtableSchemas = { 9 | name: z.literal('airtable'), 10 | resourceSettings: zAirtableResourceSettings, 11 | destinationInputEntity: zCast(), 12 | } satisfies ConnectorSchemas 13 | 14 | export const helpers = connHelpers(airtableSchemas) 15 | 16 | export const airtableDef = { 17 | metadata: { 18 | categories: ['database'], 19 | logoUrl: '/_assets/logo-airtable.svg', 20 | }, 21 | name: 'airtable', 22 | schemas: airtableSchemas, 23 | } satisfies ConnectorDef 24 | 25 | export default airtableDef 26 | -------------------------------------------------------------------------------- /connectors/connector-airtable/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './AirtableClient' 3 | export * from './def' 4 | export * from './server' 5 | // codegen:end 6 | -------------------------------------------------------------------------------- /connectors/connector-airtable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-airtable", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [], 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@usevenice/cdk": "workspace:*", 9 | "@usevenice/util": "workspace:*", 10 | "airtable": "0.11.4" 11 | }, 12 | "devDependencies": {} 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-alphavantage/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './alphavantageClient' 3 | // codegen:end 4 | -------------------------------------------------------------------------------- /connectors/connector-alphavantage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-alphavantage", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-apollo/def.ts: -------------------------------------------------------------------------------- 1 | import oas from '@opensdks/sdk-apollo/apollo.oas.json' 2 | import type {ConnectorDef, ConnectorSchemas, OpenApiSpec} from '@usevenice/cdk' 3 | import {connHelpers} from '@usevenice/cdk' 4 | import {R, z} from '@usevenice/util' 5 | 6 | export const APOLLO_ENTITY_NAME = ['contact', 'account'] as const 7 | 8 | export const apolloSchemas = { 9 | name: z.literal('apollo'), 10 | // Should get this from apollo sdk def... 11 | resourceSettings: z.object({ 12 | api_key: z.string(), 13 | }), 14 | sourceOutputEntities: R.mapToObj(APOLLO_ENTITY_NAME, (k) => [k, z.unknown()]), 15 | } satisfies ConnectorSchemas 16 | 17 | export const apolloHelpers = connHelpers(apolloSchemas) 18 | 19 | export const apolloDef = { 20 | name: 'apollo', 21 | schemas: apolloSchemas, 22 | metadata: { 23 | categories: ['sales-engagement'], 24 | displayName: 'Apollo', 25 | stage: 'beta', 26 | logoUrl: '/_assets/logo-apollo.svg', 27 | openapiSpec: {proxied: oas as OpenApiSpec}, 28 | }, 29 | } satisfies ConnectorDef 30 | 31 | export default apolloDef 32 | -------------------------------------------------------------------------------- /connectors/connector-apollo/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | // codegen:end 5 | export * from '@opensdks/sdk-apollo' 6 | -------------------------------------------------------------------------------- /connectors/connector-apollo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-apollo", 3 | "version": "0.0.0", 4 | "private": true, 5 | "module": "./index.ts", 6 | "scripts": {}, 7 | "dependencies": { 8 | "@opensdks/runtime": "^0.0.16", 9 | "@opensdks/sdk-apollo": "^0.0.18", 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | }, 13 | "devDependencies": {} 14 | } 15 | -------------------------------------------------------------------------------- /connectors/connector-beancount/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './bean-fs-utils' 3 | export * from './beancountConverters' 4 | export * from './def' 5 | export * from './server' 6 | // codegen:end 7 | -------------------------------------------------------------------------------- /connectors/connector-beancount/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-beancount", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | }, 13 | "devDependencies": {} 14 | } 15 | -------------------------------------------------------------------------------- /connectors/connector-brex/BrexClient.ts: -------------------------------------------------------------------------------- 1 | import type {InfoFromPaths} from '@usevenice/util' 2 | import {makeOpenApiClient} from '@usevenice/util' 3 | 4 | import type {paths} from './__generated__/transactions.gen' 5 | 6 | export function makeBrexClient(opts: {accessToken: string}) { 7 | const transactions = makeOpenApiClient>({ 8 | baseUrl: 'https://platform.brexapis.com', // TODO: get this from openAPI.json 9 | auth: {bearerToken: opts.accessToken}, 10 | }) 11 | 12 | return {transactions} 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-brex/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | status: development 3 | --- 4 | -------------------------------------------------------------------------------- /connectors/connector-brex/index.ts: -------------------------------------------------------------------------------- 1 | import brexDef from './def' 2 | import brexServer from './server' 3 | 4 | export const brexImpl = { 5 | ...brexDef, 6 | ...brexServer, 7 | } 8 | 9 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,types,gen}.{ts,tsx}"} 10 | export * from './BrexClient' 11 | export * from './def' 12 | export * from './server' 13 | // codegen:end 14 | -------------------------------------------------------------------------------- /connectors/connector-brex/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-brex", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [], 6 | "module": "./index.ts", 7 | "scripts": { 8 | "codegen:transactions": "openapi-typescript __generated__/transactions.openapi.json --make-paths-enum --output __generated__/transactions.gen.ts" 9 | }, 10 | "dependencies": { 11 | "@usevenice/cdk": "workspace:*", 12 | "@usevenice/util": "workspace:*" 13 | }, 14 | "devDependencies": { 15 | "openapi-typescript": "6.7.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /connectors/connector-brex/server.ts: -------------------------------------------------------------------------------- 1 | /** Used for the side effect of window.MergeLink */ 2 | import type {ConnectorServer} from '@usevenice/cdk' 3 | import {Rx, rxjs} from '@usevenice/util' 4 | 5 | import {makeBrexClient} from './BrexClient' 6 | import type {brexSchemas} from './def' 7 | import {helpers} from './def' 8 | 9 | export const brexServer = { 10 | sourceSync: ({settings}) => { 11 | const client = makeBrexClient({ 12 | accessToken: settings.accessToken, 13 | }) 14 | 15 | // TODO: Paginate obviously 16 | return rxjs 17 | .from( 18 | client.transactions 19 | .get('/v2/transactions/card/primary', {}) 20 | .then((res) => 21 | (res.items ?? [])?.map((txn) => 22 | helpers._opData('transaction', txn.id ?? '', txn), 23 | ), 24 | ), 25 | ) 26 | .pipe(Rx.mergeMap((ops) => rxjs.from(ops))) 27 | }, 28 | } satisfies ConnectorServer 29 | 30 | export default brexServer 31 | -------------------------------------------------------------------------------- /connectors/connector-copilot/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-copilot", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [], 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@usevenice/cdk": "workspace:*", 9 | "@usevenice/connector-firebase": "workspace:*", 10 | "@usevenice/util": "workspace:*" 11 | }, 12 | "devDependencies": {} 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-debug/def.ts: -------------------------------------------------------------------------------- 1 | import type {ConnectorDef, ConnectorSchemas} from '@usevenice/cdk' 2 | import {connHelpers, zWebhookInput} from '@usevenice/cdk' 3 | import {z} from '@usevenice/util' 4 | 5 | export const debugSchemas = { 6 | name: z.literal('debug'), 7 | webhookInput: zWebhookInput, 8 | resourceSettings: z.unknown(), 9 | connectorConfig: z.unknown(), 10 | sourceOutputEntity: z.unknown(), 11 | integrationData: z.unknown(), 12 | } satisfies ConnectorSchemas 13 | 14 | export const helpers = connHelpers(debugSchemas) 15 | 16 | export const debugDef = { 17 | metadata: {stage: 'hidden'}, 18 | name: 'debug', 19 | schemas: debugSchemas, 20 | } satisfies ConnectorDef 21 | 22 | export default debugDef 23 | -------------------------------------------------------------------------------- /connectors/connector-debug/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | // codegen:end 5 | -------------------------------------------------------------------------------- /connectors/connector-debug/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-debug", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [], 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@usevenice/cdk": "workspace:*", 9 | "@usevenice/util": "workspace:*" 10 | }, 11 | "devDependencies": {} 12 | } 13 | -------------------------------------------------------------------------------- /connectors/connector-debug/server.ts: -------------------------------------------------------------------------------- 1 | import type {ConnectorServer} from '@usevenice/cdk' 2 | import {logLink} from '@usevenice/cdk' 3 | import {rxjs} from '@usevenice/util' 4 | 5 | import type {debugSchemas} from './def' 6 | 7 | export const debugServer = { 8 | sourceSync: () => rxjs.EMPTY, 9 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 10 | destinationSync: () => logLink({prefix: 'debug', verbose: true}), 11 | handleWebhook: (input) => ({ 12 | resourceUpdates: [], 13 | response: {body: {echo: input}}, 14 | }), 15 | } satisfies ConnectorServer 16 | 17 | export default debugServer 18 | -------------------------------------------------------------------------------- /connectors/connector-discord/def.ts: -------------------------------------------------------------------------------- 1 | import type {ConnectorDef, ConnectorSchemas} from '@usevenice/cdk' 2 | import {connHelpers, oauthBaseSchema} from '@usevenice/cdk' 3 | import {z} from '@usevenice/util' 4 | 5 | export const discordSchemas = { 6 | name: z.literal('discord'), 7 | connectorConfig: oauthBaseSchema.connectorConfig, 8 | resourceSettings: oauthBaseSchema.resourceSettings, 9 | connectOutput: oauthBaseSchema.connectOutput, 10 | } satisfies ConnectorSchemas 11 | 12 | export const discordHelpers = connHelpers(discordSchemas) 13 | 14 | export const discordDef = { 15 | name: 'discord', 16 | schemas: discordSchemas, 17 | metadata: { 18 | displayName: 'Discord', 19 | stage: 'beta', 20 | logoUrl: '/_assets/logo-discord.svg', 21 | nangoProvider: 'discord', 22 | }, 23 | } satisfies ConnectorDef 24 | 25 | export default discordDef 26 | -------------------------------------------------------------------------------- /connectors/connector-discord/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | // codegen:end 5 | -------------------------------------------------------------------------------- /connectors/connector-discord/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-discord", 3 | "version": "0.0.0", 4 | "private": true, 5 | "module": "./index.ts", 6 | "scripts": {}, 7 | "dependencies": { 8 | "@opensdks/sdk-discord": "^0.0.14", 9 | "@usevenice/cdk": "workspace:*", 10 | "@usevenice/util": "workspace:*" 11 | }, 12 | "devDependencies": {} 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-discord/server.ts: -------------------------------------------------------------------------------- 1 | import type {ConnectorServer} from '@usevenice/cdk' 2 | 3 | import type {discordSchemas} from './def' 4 | 5 | export const discordServer = {} satisfies ConnectorServer 6 | 7 | export default discordServer 8 | -------------------------------------------------------------------------------- /connectors/connector-expensify/expensify.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | 3 | declare namespace Expensify { 4 | export interface AuthenticateResponse { 5 | accountID: number 6 | authToken: string 7 | email: string 8 | expensify_activePolicyID: string 9 | httpCode: number 10 | jsonCode: number 11 | /** Object is too complicated right now */ 12 | policy: any 13 | private_expensifyCredits: number 14 | requestID: string 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /connectors/connector-expensify/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './expensifyClient' 3 | // codegen:end 4 | -------------------------------------------------------------------------------- /connectors/connector-expensify/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-expensify", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-firebase/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './firebase-types' 4 | export * from './firebase-utils' 5 | export * from './firebaseAuth' 6 | export * from './MultiBatch' 7 | export * from './server' 8 | // codegen:end 9 | -------------------------------------------------------------------------------- /connectors/connector-firebase/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-firebase", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@firebase/app": "0.x", 11 | "@firebase/app-compat": "0.x", 12 | "@firebase/app-types": "0.x", 13 | "@firebase/auth": "*", 14 | "@usevenice/cdk": "workspace:*", 15 | "@usevenice/util": "workspace:*", 16 | "firebase": "9.8.1", 17 | "firebase-admin": "10.2.0" 18 | }, 19 | "devDependencies": {} 20 | } 21 | -------------------------------------------------------------------------------- /connectors/connector-firebase/register.node.ts: -------------------------------------------------------------------------------- 1 | import admin from 'firebase-admin' 2 | 3 | import {implementProxyFn} from '@usevenice/util' 4 | 5 | import {$admin} from './server' 6 | 7 | implementProxyFn($admin, () => admin) 8 | -------------------------------------------------------------------------------- /connectors/connector-foreceipt/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './foreceipt-utils' 4 | export * from './ForeceiptClient' 5 | export * from './server' 6 | // codegen:end 7 | -------------------------------------------------------------------------------- /connectors/connector-foreceipt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-foreceipt", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/connector-firebase": "workspace:*", 12 | "@usevenice/util": "workspace:*", 13 | "firebase": "9.8.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /connectors/connector-foreceipt/register.node.ts: -------------------------------------------------------------------------------- 1 | import '@usevenice/connector-firebase/register.node' 2 | -------------------------------------------------------------------------------- /connectors/connector-fs/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | // codegen:end 5 | -------------------------------------------------------------------------------- /connectors/connector-fs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-fs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | }, 13 | "devDependencies": {} 14 | } 15 | -------------------------------------------------------------------------------- /connectors/connector-heron/HeronClient.ts: -------------------------------------------------------------------------------- 1 | import type {InfoFromPaths} from '@usevenice/util' 2 | import {makeOpenApiClient} from '@usevenice/util' 3 | 4 | import type {paths} from './heron.gen' 5 | 6 | /** https://docs.herondata.io/authentication */ 7 | export function makeHeronClient(opts: {apiKey: string}) { 8 | const baseUrl = 'https://app.herondata.io' 9 | const client = makeOpenApiClient>({ 10 | baseUrl, 11 | auth: {basic: {username: '', password: opts.apiKey}}, 12 | }) 13 | return client 14 | } 15 | -------------------------------------------------------------------------------- /connectors/connector-heron/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | status: development 3 | --- 4 | -------------------------------------------------------------------------------- /connectors/connector-heron/index.ts: -------------------------------------------------------------------------------- 1 | import heronDef from './def' 2 | import {heronServer} from './server' 3 | 4 | export const heronImpl = { 5 | ...heronDef, 6 | ...heronServer, 7 | } 8 | 9 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,types,gen}.{ts,tsx}"} 10 | export * from './def' 11 | export * from './HeronClient' 12 | export * from './server' 13 | // codegen:end 14 | -------------------------------------------------------------------------------- /connectors/connector-heron/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-heron", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [], 6 | "module": "./index.ts", 7 | "scripts": { 8 | "codegen": "openapi-typescript https://app.herondata.io/swagger --make-paths-enum --output heron.gen.ts" 9 | }, 10 | "dependencies": { 11 | "@usevenice/cdk": "workspace:*", 12 | "@usevenice/util": "workspace:*" 13 | }, 14 | "devDependencies": { 15 | "openapi-typescript": "6.7.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /connectors/connector-lunchmoney/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './lunchmoneyClient' 4 | export * from './server' 5 | // codegen:end 6 | -------------------------------------------------------------------------------- /connectors/connector-lunchmoney/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-lunchmoney", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-mercury/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-mercury", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [], 6 | "module": "./index.ts", 7 | "scripts": { 8 | "codegen": "openapi-typescript https://dash.readme.com/api/v1/api-registry/5pyq7alhaqulga --output ./lib/mercury.gen.ts" 9 | }, 10 | "dependencies": { 11 | "@usevenice/cdk": "workspace:*", 12 | "@usevenice/util": "workspace:*" 13 | }, 14 | "devDependencies": { 15 | "openapi-typescript": "6.7.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /connectors/connector-merge/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | status: development 3 | --- 4 | -------------------------------------------------------------------------------- /connectors/connector-merge/index.ts: -------------------------------------------------------------------------------- 1 | import {mergeClient} from './client' 2 | import {mergeDef} from './def' 3 | import {mergeServer} from './server' 4 | 5 | export const mergeImpl = { 6 | ...mergeDef, 7 | ...mergeClient, 8 | ...mergeServer, 9 | } 10 | 11 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,types,gen}.{ts,tsx}"} 12 | export * from './client' 13 | export * from './def' 14 | export * from './merge-logo.svg' 15 | export * from './MergeClient' 16 | export * from './server' 17 | // codegen:end 18 | -------------------------------------------------------------------------------- /connectors/connector-merge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-merge", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [], 6 | "module": "./index.ts", 7 | "scripts": { 8 | "codegen:next:accounting": "openapi-typescript https://api.merge.dev/api/accounting/v1/schema --make-paths-enum --output merge.accounting.gen.ts" 9 | }, 10 | "dependencies": { 11 | "@usevenice/cdk": "workspace:*", 12 | "@usevenice/util": "workspace:*" 13 | }, 14 | "devDependencies": { 15 | "@mergeapi/react-merge-link": "2.0.6", 16 | "@types/react": "*", 17 | "openapi-typescript": "6.7.1" 18 | }, 19 | "peerDependencies": { 20 | "react": "*" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /connectors/connector-mongodb/def.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AnyEntityPayload, 3 | ConnectorDef, 4 | ConnectorSchemas, 5 | } from '@usevenice/cdk' 6 | import {z, zCast} from '@usevenice/util' 7 | 8 | export const zMongoConnection = z.object({ 9 | databaseUrl: z.string(), 10 | databaseName: z.string(), 11 | }) 12 | 13 | export const mongoSchemas = { 14 | name: z.literal('mongodb'), 15 | resourceSettings: zMongoConnection, 16 | destinationInputEntity: zCast(), 17 | } satisfies ConnectorSchemas 18 | 19 | export const mongoDef = { 20 | name: 'mongodb', 21 | schemas: mongoSchemas, 22 | metadata: {categories: ['database'], logoUrl: '/_assets/logo-mongodb.png'}, 23 | } satisfies ConnectorDef 24 | 25 | export default mongoDef 26 | -------------------------------------------------------------------------------- /connectors/connector-mongodb/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | // codegen:end 5 | -------------------------------------------------------------------------------- /connectors/connector-mongodb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-mongodb", 3 | "version": "0.0.0", 4 | "private": true, 5 | "module": "./index.ts", 6 | "dependencies": { 7 | "@usevenice/cdk": "workspace:*", 8 | "@usevenice/util": "workspace:*", 9 | "mongodb": "4.9.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /connectors/connector-moota/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './mootaClient' 4 | export * from './server' 5 | // codegen:end 6 | -------------------------------------------------------------------------------- /connectors/connector-moota/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-moota", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-notion/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-notion", 3 | "version": "0.0.0", 4 | "private": true, 5 | "module": "./index.ts", 6 | "scripts": { 7 | "download": "curl --fail https://api.apis.guru/v2/specs/notion.com/1.0.0/openapi.yaml > ./notion.openapi.gen.yaml", 8 | "generate": "openapi-typescript ./notion.openapi.gen.yaml --output ./notion.openapi.gen.d.ts" 9 | }, 10 | "dependencies": {}, 11 | "devDependencies": { 12 | "openapi-typescript": "6.7.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /connectors/connector-onebrick/index.ts: -------------------------------------------------------------------------------- 1 | import onebrickClientConector from './client' 2 | import oneBrickDef from './def' 3 | import onebrickServerConnector from './server' 4 | 5 | export const oneBrickProvider = { 6 | ...oneBrickDef, 7 | ...onebrickClientConector, 8 | ...onebrickServerConnector, 9 | } 10 | 11 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 12 | export * from './client' 13 | export * from './def' 14 | export * from './onebrick-utils' 15 | export * from './OneBrickClient' 16 | export * from './server' 17 | // codegen:end 18 | -------------------------------------------------------------------------------- /connectors/connector-onebrick/onebrick-utils.ts: -------------------------------------------------------------------------------- 1 | import type {OneBrickEnvName} from './OneBrickClient' 2 | 3 | export function inferOneBrickEnvFromToken( 4 | publicOrAccessToken: string, 5 | ): OneBrickEnvName | null { 6 | const regex = /^(access|public)-(sandbox|development|production)-/ 7 | const match = regex.exec(publicOrAccessToken) 8 | 9 | if (match) { 10 | return match[2] as OneBrickEnvName 11 | } 12 | 13 | return null 14 | } 15 | -------------------------------------------------------------------------------- /connectors/connector-onebrick/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-onebrick", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "scripts": { 10 | "//": "Cannot use --make-paths-enum due to https://github.com/drwpow/openapi-typescript/issues/935", 11 | "codegen:next": "openapi-typescript https://dash.readme.com/api/v1/api-registry/rwkfe1gl7puob14 --output onebrick.gen.ts" 12 | }, 13 | "dependencies": { 14 | "@usevenice/cdk": "workspace:*", 15 | "@usevenice/util": "workspace:*" 16 | }, 17 | "devDependencies": { 18 | "@types/react": "*", 19 | "openapi-typescript": "6.7.1" 20 | }, 21 | "peerDependencies": { 22 | "react": "*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /connectors/connector-outreach/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | // codegen:end 5 | 6 | export * from '@opensdks/sdk-outreach' 7 | -------------------------------------------------------------------------------- /connectors/connector-outreach/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-outreach", 3 | "version": "0.0.0", 4 | "private": true, 5 | "module": "./index.ts", 6 | "dependencies": { 7 | "@opensdks/runtime": "^0.0.16", 8 | "@opensdks/sdk-outreach": "0.0.15", 9 | "@usevenice/cdk": "workspace:*", 10 | "@usevenice/util": "workspace:*" 11 | }, 12 | "devDependencies": {} 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-plaid/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | status: production 3 | --- 4 | -------------------------------------------------------------------------------- /connectors/connector-plaid/index.ts: -------------------------------------------------------------------------------- 1 | import plaidClientConnector from './client' 2 | import plaidDef from './def' 3 | import plaidServerConnector from './server' 4 | 5 | export {PlaidSDKTypes} from '@opensdks/sdk-plaid' 6 | 7 | export const plaidProvider = { 8 | ...plaidDef, 9 | ...plaidClientConnector, 10 | ...plaidServerConnector, 11 | } 12 | 13 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,types,gen}.{ts,tsx}"} 14 | export * from './client' 15 | export * from './def' 16 | export * from './plaid-utils' 17 | export * from './PlaidClient' 18 | export * from './request.noop' 19 | export * from './server' 20 | // codegen:end 21 | 22 | // Consider using "plaid" as peerDependency to reduce 23 | // code bloat when shipping to react native environment 24 | // Ideally however we should have separate packages for 25 | // client / server usage, but that's a bit too much work for now 26 | -------------------------------------------------------------------------------- /connectors/connector-plaid/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-plaid", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@opensdks/runtime": "^0.0.16", 11 | "@opensdks/sdk-plaid": "^0.0.14", 12 | "@t3-oss/env-core": "0.7.1", 13 | "@usevenice/cdk": "workspace:*", 14 | "@usevenice/util": "workspace:*", 15 | "plaid": "12.3.0", 16 | "react-plaid-link": "3.3.2" 17 | }, 18 | "devDependencies": { 19 | "@types/react": "*", 20 | "prettier": "3.1.0", 21 | "yamljs": "0.3.0" 22 | }, 23 | "peerDependencies": { 24 | "react": "*" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /connectors/connector-plaid/plaid-utils.ts: -------------------------------------------------------------------------------- 1 | import type {PlaidEnvName} from './legacy/plaid-helpers' 2 | 3 | export function inferPlaidEnvFromToken( 4 | publicOrAccessToken: string, 5 | ): PlaidEnvName { 6 | const regex = /^(access|public)-(sandbox|development|production)-/ 7 | const match = regex.exec(publicOrAccessToken) 8 | 9 | if (match) { 10 | return match[2] as PlaidEnvName 11 | } 12 | throw new Error('Invalid token without env') 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-plaid/request.noop.ts: -------------------------------------------------------------------------------- 1 | export const request = (_config: unknown, _options: unknown) => { 2 | throw new Error('Not implemented') 3 | } 4 | -------------------------------------------------------------------------------- /connectors/connector-postgres/index.ts: -------------------------------------------------------------------------------- 1 | // Should this actually be called `connector-export` or `connector-standard`? Similar to `connector-spreadsheet`? 2 | // Previously this used to be called `connector-alka`, but given alka is no longer relevant, how do we want to define this? 3 | 4 | import postgresDef from './def' 5 | import postgresServer from './server' 6 | 7 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 8 | export * from './def' 9 | export * from './makePostgresClient' 10 | export * from './server' 11 | // codegen:end 12 | 13 | export const postgresProvider = { 14 | ...postgresDef, 15 | ...postgresServer, 16 | } 17 | -------------------------------------------------------------------------------- /connectors/connector-postgres/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-postgres", 3 | "version": "0.0.0", 4 | "private": true, 5 | "module": "./index.ts", 6 | "dependencies": { 7 | "@slonik/migrator": "0.11.3", 8 | "@usevenice/cdk": "workspace:*", 9 | "@usevenice/util": "workspace:*", 10 | "handlebars": "4.7.7", 11 | "pg": "8.8.0", 12 | "pg-native": "3.0.1", 13 | "slonik": "30.3.1", 14 | "slonik-interceptor-preset": "1.2.10", 15 | "zod": "3.22.4" 16 | }, 17 | "devDependencies": { 18 | "@types/pg": "8.6.5" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /connectors/connector-qbo/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | // codegen:end 5 | export * from '@opensdks/sdk-qbo' 6 | -------------------------------------------------------------------------------- /connectors/connector-qbo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-qbo", 3 | "version": "0.0.0", 4 | "private": true, 5 | "module": "./index.ts", 6 | "dependencies": { 7 | "@opensdks/runtime": "^0.0.16", 8 | "@opensdks/sdk-qbo": "^0.0.14", 9 | "@usevenice/cdk": "workspace:*", 10 | "@usevenice/util": "workspace:*" 11 | }, 12 | "devDependencies": {} 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-ramp/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './RampClient' 4 | export * from './server' 5 | // codegen:end 6 | -------------------------------------------------------------------------------- /connectors/connector-ramp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-ramp", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-salesloft/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | // codegen:end 5 | export * from '@opensdks/sdk-salesloft' 6 | -------------------------------------------------------------------------------- /connectors/connector-salesloft/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-salesloft", 3 | "version": "0.0.0", 4 | "private": true, 5 | "module": "./index.ts", 6 | "dependencies": { 7 | "@opensdks/runtime": "^0.0.16", 8 | "@opensdks/sdk-salesloft": "0.0.16", 9 | "@usevenice/cdk": "workspace:*", 10 | "@usevenice/util": "workspace:*" 11 | }, 12 | "devDependencies": {} 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-saltedge/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './saltedgeClient' 4 | export * from './server' 5 | // codegen:end 6 | -------------------------------------------------------------------------------- /connectors/connector-saltedge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-saltedge", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-splitwise/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | export * from './splitwise-schema' 5 | export * from './SplitwiseClientNext' 6 | // codegen:end 7 | -------------------------------------------------------------------------------- /connectors/connector-splitwise/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-splitwise", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-spreadsheet/RowIdMaker.spec.ts: -------------------------------------------------------------------------------- 1 | import {RowIdMaker} from './RowIdMaker' 2 | 3 | test('uniqueIdForRow for duplicate rows', () => { 4 | const maker = new RowIdMaker() 5 | const row = { 6 | Date: '03/06/2019', 7 | Description: 'ATM Debit', 8 | Amount: '-115.19,03', 9 | Details: '06 SP * ATOMS SHOES HTTPSWEARATOMCA / 5089/', 10 | } 11 | const id1 = maker.uniqueIdForRow(row) 12 | const id2 = maker.uniqueIdForRow(row) 13 | expect(id1).not.toEqual(id2) 14 | 15 | expect(id2).toBe(`${id1}-2`) 16 | }) 17 | -------------------------------------------------------------------------------- /connectors/connector-spreadsheet/formats/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './format-alliant-credit-union' 3 | export * from './format-apple-card' 4 | export * from './format-bbva-mexico' 5 | export * from './format-brex-cash' 6 | export * from './format-brex' 7 | export * from './format-capitalone-bank' 8 | export * from './format-capitalone' 9 | export * from './format-coinbase' 10 | export * from './format-coinkeeper' 11 | export * from './format-etrade' 12 | export * from './format-first-republic' 13 | export * from './format-ramp' 14 | export * from './format-wise' 15 | // codegen:end 16 | -------------------------------------------------------------------------------- /connectors/connector-spreadsheet/index.ts: -------------------------------------------------------------------------------- 1 | import Papa from 'papaparse' 2 | 3 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 4 | export * from './def' 5 | export * from './formats/index' 6 | export * from './makeImportFormat' 7 | export * from './RowIdMaker' 8 | export * from './server' 9 | // codegen:end 10 | export {Papa} 11 | -------------------------------------------------------------------------------- /connectors/connector-spreadsheet/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-spreadsheet", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*", 12 | "papaparse": "5.3.2", 13 | "xlsx": "0.17.5" 14 | }, 15 | "devDependencies": { 16 | "@types/papaparse": "5.3.5" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /connectors/connector-stripe/StripeClient.ts: -------------------------------------------------------------------------------- 1 | import type {InfoFromPaths} from '@usevenice/util' 2 | import {makeOpenApiClient} from '@usevenice/util' 3 | 4 | import type {operations, paths} from './stripe.gen' 5 | 6 | export function makeStripeClient(opts: { 7 | apiKey: string 8 | /** API version */ 9 | stripeVersion?: operations['PostWebhookEndpoints']['requestBody']['content']['application/x-www-form-urlencoded']['api_version'] 10 | }) { 11 | const baseUrl = 'https://api.stripe.com' 12 | const client = makeOpenApiClient>({ 13 | baseUrl, 14 | auth: {basic: {username: opts.apiKey, password: ''}}, 15 | headers: { 16 | ...(opts.stripeVersion && {'Stripe-Version': `${opts.stripeVersion}`}), 17 | }, 18 | }) 19 | return client 20 | } 21 | -------------------------------------------------------------------------------- /connectors/connector-stripe/index.ts: -------------------------------------------------------------------------------- 1 | import {helpers, stripeDef} from './def' 2 | import stripeServer from './server' 3 | 4 | export const stripeImpl = { 5 | ...stripeDef, 6 | ...stripeServer, 7 | helpers, 8 | } 9 | 10 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 11 | export * from './def' 12 | export * from './server' 13 | export * from './StripeClient' 14 | // codegen:end 15 | -------------------------------------------------------------------------------- /connectors/connector-stripe/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-stripe", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "scripts": { 10 | "codegen": "openapi-typescript https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.yaml --make-paths-enum --output stripe.gen.ts" 11 | }, 12 | "dependencies": { 13 | "@usevenice/cdk": "workspace:*", 14 | "@usevenice/util": "workspace:*" 15 | }, 16 | "devDependencies": { 17 | "openapi-typescript": "6.7.1" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /connectors/connector-teller/index.ts: -------------------------------------------------------------------------------- 1 | import tellerClient from './client' 2 | import tellerDef from './def' 3 | import tellerServer from './server' 4 | 5 | export const tellerProvider = { 6 | ...tellerDef, 7 | ...tellerClient, 8 | ...tellerServer, 9 | } 10 | 11 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 12 | export * from './client' 13 | export * from './def' 14 | export * from './server' 15 | export * from './TellerClient' 16 | // codegen:end 17 | -------------------------------------------------------------------------------- /connectors/connector-teller/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-teller", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | }, 13 | "devDependencies": { 14 | "@types/react": "*" 15 | }, 16 | "peerDependencies": { 17 | "react": "*" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /connectors/connector-toggl/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | export * from './TogglCient' 5 | // codegen:end 6 | -------------------------------------------------------------------------------- /connectors/connector-toggl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-toggl", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-twenty/def.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | ConnectorDef, 3 | ConnectorSchemas, 4 | EntityPayloadWithRaw, 5 | } from '@usevenice/cdk' 6 | import {connHelpers} from '@usevenice/cdk' 7 | import {z, zCast} from '@usevenice/util' 8 | 9 | export const twentySchemas = { 10 | name: z.literal('twenty'), 11 | resourceSettings: z.object({ 12 | access_token: z.string(), 13 | }), 14 | destinationInputEntity: zCast(), 15 | } satisfies ConnectorSchemas 16 | 17 | export const helpers = connHelpers(twentySchemas) 18 | 19 | export const twentyDef = { 20 | metadata: { 21 | categories: ['crm'], 22 | logoUrl: '/_assets/logo-twenty.svg', 23 | }, 24 | name: 'twenty', 25 | schemas: twentySchemas, 26 | } satisfies ConnectorDef 27 | 28 | export default twentyDef 29 | -------------------------------------------------------------------------------- /connectors/connector-twenty/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | // codegen:end 5 | -------------------------------------------------------------------------------- /connectors/connector-twenty/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-twenty", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [], 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@opensdks/sdk-twenty": "^0.0.3", 9 | "@opensdks/util-zod": "^0.0.15", 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | }, 13 | "devDependencies": {} 14 | } 15 | -------------------------------------------------------------------------------- /connectors/connector-venmo/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './venmo-helpers' 4 | export * from './VenmoClient' 5 | export * from './VenmoProvider' 6 | // codegen:end 7 | -------------------------------------------------------------------------------- /connectors/connector-venmo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-venmo", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-vercel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-vercel", 3 | "version": "0.0.0", 4 | "private": true, 5 | "module": "./index.ts", 6 | "scripts": { 7 | "download": "curl --fail https://api.apis.guru/v2/specs/vercel.com/0.0.1/openapi.yaml > ./vercel.openapi.gen.yaml", 8 | "generate": "openapi-typescript ./vercel.openapi.gen.yaml --output ./vercel.openapi.gen.d.ts" 9 | }, 10 | "dependencies": {}, 11 | "devDependencies": { 12 | "openapi-typescript": "6.7.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /connectors/connector-webhook/def.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | AnyEntityPayload, 3 | ConnectorDef, 4 | ConnectorSchemas, 5 | } from '@usevenice/cdk' 6 | import {connHelpers} from '@usevenice/cdk' 7 | import {z, zCast} from '@usevenice/util' 8 | 9 | export const webhookSchemas = { 10 | name: z.literal('webhook'), 11 | resourceSettings: z.object({ 12 | destinationUrl: z.string(), 13 | }), 14 | destinationInputEntity: zCast(), 15 | } satisfies ConnectorSchemas 16 | 17 | export const webhookHelpers = connHelpers(webhookSchemas) 18 | 19 | export const webhookDef = { 20 | name: 'webhook', 21 | metadata: {categories: ['streaming'], logoUrl: '/_assets/logo-webhook.png'}, 22 | 23 | schemas: webhookSchemas, 24 | } satisfies ConnectorDef 25 | 26 | export default webhookDef 27 | -------------------------------------------------------------------------------- /connectors/connector-webhook/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | // codegen:end 5 | -------------------------------------------------------------------------------- /connectors/connector-webhook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-webhook", 3 | "version": "0.0.0", 4 | "private": true, 5 | "module": "./index.ts", 6 | "dependencies": { 7 | "@usevenice/cdk": "workspace:*", 8 | "@usevenice/util": "workspace:*" 9 | }, 10 | "devDependencies": {} 11 | } 12 | -------------------------------------------------------------------------------- /connectors/connector-wise/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './def' 3 | export * from './server' 4 | export * from './WiseClient' 5 | // codegen:end 6 | -------------------------------------------------------------------------------- /connectors/connector-wise/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-wise", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "dependencies": { 10 | "@usevenice/cdk": "workspace:*", 11 | "@usevenice/util": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /connectors/connector-xero/index.ts: -------------------------------------------------------------------------------- 1 | import type {initXeroSDK} from '@opensdks/sdk-xero' 2 | 3 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 4 | export * from './def' 5 | export * from './server' 6 | // codegen:end 7 | 8 | export * from '@opensdks/sdk-xero' 9 | 10 | export type XeroSDK = ReturnType 11 | -------------------------------------------------------------------------------- /connectors/connector-xero/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-xero", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [], 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@opensdks/runtime": "^0.0.19", 9 | "@opensdks/sdk-xero": "^0.0.7", 10 | "@opensdks/util-zod": "^0.0.15", 11 | "@usevenice/cdk": "workspace:*", 12 | "@usevenice/util": "workspace:*" 13 | }, 14 | "devDependencies": {} 15 | } 16 | -------------------------------------------------------------------------------- /connectors/connector-yodlee/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | status: development 3 | --- 4 | -------------------------------------------------------------------------------- /connectors/connector-yodlee/index.ts: -------------------------------------------------------------------------------- 1 | import yodleeClientConnector from './client' 2 | import yodleeDef from './def' 3 | import {yodleeServerConnector} from './server' 4 | 5 | export const yodleeProvider = { 6 | ...yodleeDef, 7 | ...yodleeClientConnector, 8 | ...yodleeServerConnector, 9 | } 10 | 11 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "{./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx},./*.generated/*}"} 12 | export * from './client' 13 | export * from './def' 14 | export * from './request.noop' 15 | export * from './server' 16 | export * from './yodlee-utils' 17 | export * from './yodlee.types' 18 | export * from './YodleeClient' 19 | // codegen:end 20 | -------------------------------------------------------------------------------- /connectors/connector-yodlee/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connector-yodlee", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [ 6 | "register.node.ts" 7 | ], 8 | "module": "./index.ts", 9 | "scripts": { 10 | "download": "curl --fail https://raw.githubusercontent.com/Yodlee/OpenAPI/main/swagger.yaml > yodlee.oas.yaml", 11 | "generate": "pnpm generate:oas && pnpm generate:types", 12 | "generate:oas": "swagger2openapi ./yodlee.oas.yaml | prettier --parser json > ./yodlee.oas.json", 13 | "generate:types": "openapi-typescript ./yodlee.oas.json --output yodlee.oas.d.ts" 14 | }, 15 | "dependencies": { 16 | "@usevenice/cdk": "workspace:*", 17 | "@usevenice/openapi-client": "workspace:*", 18 | "@usevenice/util": "workspace:*" 19 | }, 20 | "devDependencies": { 21 | "@types/react": "*", 22 | "openapi-typescript": "6.7.1", 23 | "prettier": "3.1.0", 24 | "swagger2openapi": "7.0.8" 25 | }, 26 | "peerDependencies": { 27 | "react": "*" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /connectors/connector-yodlee/request.noop.ts: -------------------------------------------------------------------------------- 1 | export const request = (_config: unknown, _options: unknown) => { 2 | throw new Error('Not implemented') 3 | } 4 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | # NOTE: Postgres (and certainly supabase) is not a requirement for usage in Venice, though it is the default set 2 | # Therefore this docker-compose file is entirely optional 3 | version: '3' 4 | services: 5 | postgres: 6 | image: supabase/postgres 7 | ports: 8 | - 5432:5432 9 | # command: postgres -c log_statement=all 10 | restart: always 11 | environment: 12 | POSTGRES_DB: postgres # Only database named `postgres` works with pg_cron by default 13 | POSTGRES_PASSWORD: masterpass 14 | -------------------------------------------------------------------------------- /docs/api-reference/connect/post-connectmagic-link.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: post /connect/magic-link 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/connect/post-connecttoken.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: post /connect/token 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/connectors/get-connector-1.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /connector/{name} 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/connectors/get-connector-oas.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /connector/{name}/oas 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/connectors/get-connector-schemas.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /connector/{name}/schemas 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/connectors/get-connector.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /connector 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/delete-coreconnector_config.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: delete /core/connector_config/{id} 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/delete-corepipeline.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: delete /core/pipeline/{id} 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/delete-coreresource.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: delete /core/resource/{id} 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/get-coreconnector_config-1.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /core/connector_config/{id} 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/get-coreconnector_config.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /core/connector_config 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/get-coreconnector_config_info.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /core/connector_config_info 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/get-corepipeline.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /core/pipeline 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/get-coreresource-1.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /core/resource/{id} 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/get-coreresource.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /core/resource 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/patch-coreresource.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: patch /core/resource/{id} 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/post-coreconnector_config.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: post /core/connector_config 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/post-coreresource-source_sync.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: post /core/resource/{id}/source_sync 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/core/post-coreresource.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: post /core/resource 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/get-openapijson.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /openapi.json 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/internal/get-debugraw-schemas.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /debug/raw-schemas 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/internal/health-check.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /health 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/internal/post-passthrough.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: post /passthrough 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/verticals/get-verticalsaccountingaccount.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /verticals/accounting/account 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/verticals/get-verticalsaccountingexpense.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /verticals/accounting/expense 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/verticals/get-verticalsaccountingvendor.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /verticals/accounting/vendor 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/verticals/get-verticalsinvestmentaccount.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /verticals/investment/account 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/verticals/get-verticalsinvestmentholding.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /verticals/investment/holding 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/verticals/get-verticalsinvestmentsecurity.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /verticals/investment/security 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/verticals/get-verticalsinvestmenttransaction.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /verticals/investment/transaction 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/verticals/get-verticalsptaaccount.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /verticals/pta/account 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/verticals/get-verticalsptacommodity.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /verticals/pta/commodity 3 | --- -------------------------------------------------------------------------------- /docs/api-reference/verticals/get-verticalsptatransaction.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: get /verticals/pta/transaction 3 | --- -------------------------------------------------------------------------------- /docs/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/docs/images/background.png -------------------------------------------------------------------------------- /docs/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/docs/images/favicon.png -------------------------------------------------------------------------------- /docs/images/models.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/docs/images/models.png -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/docs", 3 | "scripts": { 4 | "generate": "pnpm run generate:api-pages && pnpm run generate:mint", 5 | "generate:api-pages": "rm -rf api-reference && mkdir -p api-reference && mintlify-scrape openapi-file -o api-reference ./venice.oas.json | tail -n +2 > ./api-reference/index.json", 6 | "generate:mint": "node --loader tsx mint.ts mint.json" 7 | }, 8 | "devDependencies": { 9 | "@mintlify/scraping": "^3.0.64", 10 | "@opensdks/runtime": "^0.0.16", 11 | "@opensdks/sdk-discord": "^0.0.14", 12 | "@opensdks/sdk-openai": "^0.0.14", 13 | "@opensdks/sdk-slack": "^0.0.14", 14 | "@opensdks/sdk-venice": "^0.0.14", 15 | "@usevenice/sdk": "workspace:*", 16 | "mintlify": "4.0.59" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/samples/banking-test.ts: -------------------------------------------------------------------------------- 1 | import {createVeniceClient} from '@usevenice/sdk' 2 | 3 | const venice = createVeniceClient({ 4 | apiKey: process.env['_VENICE_API_KEY'], 5 | apiHost: process.env['_VENICE_API_HOST'], 6 | // resourceId: process.env['_QBO_RESOURCE_ID'], 7 | resourceId: process.env['_XERO_RESOURCE_ID'], 8 | }) 9 | 10 | void venice.GET('/verticals/banking/category').then((r) => { 11 | console.log(r.data) 12 | }) 13 | 14 | // void venice 15 | // .POST('/core/resource/{id}/source_sync', { 16 | // params: {path: {id: process.env['_APOLLO_RESOURCE_ID']!}}, 17 | // body: {streams: {contact: true}}, 18 | // }) 19 | // .then((r) => { 20 | // console.log(r.data) 21 | // }) 22 | -------------------------------------------------------------------------------- /docs/samples/proxy-test.mts: -------------------------------------------------------------------------------- 1 | await fetch('https://httpbin.org/anything', { 2 | method: 'POST', 3 | body: JSON.stringify({foo: 'bar'}), 4 | }) 5 | -------------------------------------------------------------------------------- /docs/samples/sales-engagement-test.ts: -------------------------------------------------------------------------------- 1 | import {createVeniceClient} from '@usevenice/sdk' 2 | 3 | const venice = createVeniceClient({ 4 | apiKey: process.env['_VENICE_API_KEY'], 5 | apiHost: process.env['_VENICE_API_HOST'], 6 | resourceId: process.env['_APOLLO_RESOURCE_ID'], 7 | // resourceId: process.env['_OUTREACH_RESOURCE_ID'], 8 | // resourceId: process.env['_SALESLOFT_RESOURCE_ID'], 9 | }) 10 | 11 | void venice.GET('/verticals/sales-engagement/contacts').then((r) => { 12 | console.log(r.data) 13 | }) 14 | 15 | // void venice 16 | // .POST('/core/resource/{id}/source_sync', { 17 | // params: {path: {id: process.env['_APOLLO_RESOURCE_ID']!}}, 18 | // body: {streams: {contact: true}}, 19 | // }) 20 | // .then((r) => { 21 | // console.log(r.data) 22 | // }) 23 | -------------------------------------------------------------------------------- /docs/support/attribution.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Attribution 3 | description: Giving thanks 🙏 4 | --- 5 | 6 | Venice would like to thank the following: 7 | 8 | - Beautiful docs by [Mintlify](https://mintlify.com) 9 | - Hosting by [Vercel](https://vercel.com) 10 | - Database support by [Supabase](https://supabase.com) 11 | 12 | We'd like to also thank & credit our image resources: 13 | - [Server image](https://www.freepik.com/free-vector/server-room-cloud-storage-icon-datacenter-database-concept-data-exchange-process_3628676.htm) by fullvector on Freepik 14 | - [Bootstrap icons](https://www.figma.com/community/file/1172931415891390979) by smrkv 15 | - [Free FontAwesome icons](https://fontawesome.com/license/free) by Fonticons 16 | - [Fintech Logos](https://www.figma.com/community/file/1041824726819878251) by Om Suthar 17 | -------------------------------------------------------------------------------- /docs/support/contact-us.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Contact us 3 | description: Need help? We're on your team. 4 | --- 5 | 6 | 7 | Join our community & help us build the future of finance together 8 | 9 | 10 | 11 | Reach out to our support team and we'll be in touch soon 12 | 13 | 14 | 15 | Need a custom integration? We're happy to help 16 | -------------------------------------------------------------------------------- /docs/technical/apis.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: APIs 3 | description: How data is structured within Venice's unified API 4 | --- 5 | 6 | Please see the [REST API docs](https://app.venice.is/api-access/rest) for 7 | data models & schema information. 8 | 9 | Note that Venice currently supports the following APIs: 10 | 11 | - [GraphQL](https://app.venice.is/api-access/graphql) 12 | - [REST](https://app.venice.is/api-access/rest) 13 | 14 | If you'd like access to other APIs, please [contact us](mailto:hi@venice.is). 15 | 16 | - Realtime API (e.g. via websockets) to receive real-time notifications on 17 | database row insert / update / deletions 18 | - Dedicated database to execute raw SQL queries (for backends, data analysis, etc.) 19 | -------------------------------------------------------------------------------- /docs/technical/architecture.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Architecture 3 | description: We've built Venice from the ground up to do the hard work for you. 4 | --- 5 | 6 | 7 | 8 | Easily connect to thousands of financial institutions to automatically or manually sync data into Venice. 9 | 10 | 11 | Your data, your way. Easily extend Venice to connect new data sources. 12 | 13 | 14 | No code or full code, drop down to any level of abstraction you need. 15 | 16 | 17 | Fast and efficient sync that can be called idempotently. 18 | 19 | 20 | Get connection and data updates in real time. 21 | 22 | 23 | 24 | --- 25 | 26 | 27 | Want to help teach Venice new tricks? We welcome pull requests & feature requests! 28 | -------------------------------------------------------------------------------- /docs/technical/open-source.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Open source 3 | description: Teach Venice new things and achieve more together as a community. 4 | --- 5 | 6 | Venice is proudly open source ([ELv2 license](https://www.elastic.co/licensing/elastic-license)). 7 | The best way to support thousands of companies & millions of people is to empower 8 | thousands of developers to build Venice with us in the open. 9 | 10 | 11 | Join our community of developers & founders building the future of finance and 12 | help us build **frictionless financial data**. 13 | 14 | 15 | 16 | Teach Venice new tricks—like piping data in and out of custom data sources—or 17 | help us build Venice in the open. 18 | 19 | 20 | 21 | Need a custom integration? We're happy to help or feel free to roll up your sleeves 22 | and implement it yourself. Either way, Venice is here to support you! 23 | -------------------------------------------------------------------------------- /docs/venice.oas.json: -------------------------------------------------------------------------------- 1 | ../kits/sdk/venice.oas.json -------------------------------------------------------------------------------- /env.d.ts: -------------------------------------------------------------------------------- 1 | declare type ISODate = string 2 | declare type ISOTime = string 3 | declare type ISODateTime = string 4 | declare type ISOInterval = string 5 | 6 | declare type Unit = _Brand 7 | declare type ScheduleExpression = _Brand 8 | declare type DateRangeExpression = _Brand 9 | declare type MathExpression = _Brand 10 | declare type MixedPrecisionDateExpression = _Brand< 11 | string, 12 | 'MixedPrecisionDateExpression' 13 | > 14 | 15 | declare type ExternalId = _Brand 16 | declare type DeprecatedUserId = _Brand 17 | declare type DeprecatedLedgerId = _Brand 18 | declare type AccountId = _Brand 19 | declare type CommodityId = _Brand 20 | declare type TransactionId = _Brand 21 | declare type PostingId = _Brand 22 | 23 | // MARK: - Utils 24 | 25 | type _Brand< 26 | TBase, 27 | TBranding, 28 | TReservedName extends string = '__type__', 29 | > = import('ts-brand').Brand 30 | -------------------------------------------------------------------------------- /github/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/github/github.png -------------------------------------------------------------------------------- /github/join-community.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/github/join-community.png -------------------------------------------------------------------------------- /github/read-docs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/github/read-docs.png -------------------------------------------------------------------------------- /github/sign-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/github/sign-up.png -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('@jest/types').Config.ProjectConfig} 3 | */ 4 | module.exports = { 5 | setupFiles: ['jest-date-mock'], 6 | testEnvironment: 'node', 7 | testPathIgnorePatterns: [ 8 | '/node_modules/', 9 | '/apps/web/.next/', 10 | '/apps/web/out/', 11 | ], 12 | watchPathIgnorePatterns: [ 13 | '\\.gen\\.d\\.ts', 14 | '\\.gen\\.ts', 15 | '\\.gen\\.json', 16 | '\\.schema\\.json', 17 | ], 18 | testRegex: '\\.(spec|test)\\.[jt]sx?$', 19 | transform: { 20 | '^.+\\.(js|ts|tsx)$': [ 21 | 'esbuild-jest', 22 | { 23 | sourcemap: true, 24 | target: 'node14', 25 | format: 'cjs', 26 | }, 27 | ], 28 | }, 29 | watchPlugins: [ 30 | 'jest-watch-typeahead/filename', 31 | 'jest-watch-typeahead/testname', 32 | ], 33 | } 34 | -------------------------------------------------------------------------------- /kits/cdk/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /kits/cdk/connector-utils.ts: -------------------------------------------------------------------------------- 1 | import {z} from '@usevenice/zod' 2 | 3 | export const _zOauthConfig = z.object({ 4 | clientId: z.string(), 5 | clientSecret: z.string(), 6 | }) 7 | 8 | export const zCcfgAuth = { 9 | oauth: z.object({oauth: _zOauthConfig}), 10 | oauthOrApikeyAuth: z.object({ 11 | oauth: z 12 | .union([ 13 | z.null().describe('No oauth'), 14 | _zOauthConfig.describe('Configure oauth'), 15 | ]) 16 | .optional() 17 | .describe('Oauth support'), 18 | apikeyAuth: z.boolean().optional().describe('API key auth support'), 19 | }), 20 | } 21 | -------------------------------------------------------------------------------- /kits/cdk/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{spec,test,fixture}.{ts,tsx}"} 2 | export * from './base-links' 3 | export * from './connector-meta.types' 4 | export * from './connector-utils' 5 | export * from './connector.types' 6 | export * from './entity-links' 7 | export * from './frontend-utils' 8 | export * from './id.types' 9 | export * from './metaForConnector' 10 | export * from './models' 11 | export * from './nango/index' 12 | export * from './protocol' 13 | export * from './sync' 14 | export * from './verticals' 15 | export * from './viewer' 16 | // codegen:end 17 | -------------------------------------------------------------------------------- /kits/cdk/nango/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{spec,test,fixture}.{ts,tsx}"} 2 | export * from './NangoClient' 3 | export * from './nangoProxyLink' 4 | export * from './oauthConnector' 5 | // codegen:end 6 | -------------------------------------------------------------------------------- /kits/cdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/cdk", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": false, 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@opensdks/runtime": "^0.0.16", 9 | "@trpc/server": "10.40.0", 10 | "@usevenice/util": "workspace:*", 11 | "@usevenice/zod": "workspace:*", 12 | "jsonwebtoken": "9.0.0", 13 | "react-script-hook": "1.7.2" 14 | }, 15 | "devDependencies": { 16 | "@lilyrose2798/trpc-openapi": "1.3.10", 17 | "@nangohq/frontend": "0.33.8", 18 | "@opensdks/sdk-qbo": "0.0.11", 19 | "@types/jsonwebtoken": "9.0.2", 20 | "@types/react": "*", 21 | "openapi3-ts": "4.1.2" 22 | }, 23 | "peerDependencies": { 24 | "react": "*" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /kits/cdk/verticals.ts: -------------------------------------------------------------------------------- 1 | export * from '../../verticals/vertical-accounting' 2 | export * from '../../verticals/vertical-banking' 3 | export * from '../../verticals/vertical-investment' 4 | export * from '../../verticals/vertical-pta' 5 | export * from '../../verticals/vertical-sales-engagement' 6 | 7 | // TODO: Refactor vertical specific logic out of connectors and thus cdk 8 | // Should be self-contained inside each vertical instead. 9 | -------------------------------------------------------------------------------- /kits/connect/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | dist/ 3 | build/ 4 | -------------------------------------------------------------------------------- /kits/connect/.npmignore: -------------------------------------------------------------------------------- 1 | tsup.config.ts 2 | tsconfig.json 3 | -------------------------------------------------------------------------------- /kits/connect/index.ts: -------------------------------------------------------------------------------- 1 | // Do not but any other logic in this file, which is only used to re-export from 2 | // src/index so that code compiles inside the monorepo without building 3 | export * from './src/index' 4 | -------------------------------------------------------------------------------- /kits/connect/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/connect", 3 | "version": "0.1.11", 4 | "sideEffects": false, 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsc -p ./tsconfig.json", 9 | "clean": "rm -rf ./dist", 10 | "pub": "pnpm publish --no-git-checks" 11 | }, 12 | "dependencies": { 13 | "@usevenice/sdk": "workspace:*", 14 | "zod": "3.22.4" 15 | }, 16 | "devDependencies": { 17 | "@types/react": "*", 18 | "typescript": "*" 19 | }, 20 | "peerDependencies": { 21 | "react": "*" 22 | }, 23 | "publishConfig": { 24 | "access": "public" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /kits/connect/src/common.ts: -------------------------------------------------------------------------------- 1 | import {z} from 'zod' 2 | 3 | export const zFrameMessage = z.discriminatedUnion('type', [ 4 | z.object({ 5 | type: z.literal('SUCCESS'), 6 | data: z.object({resourceId: z.string()}), // Need to better type resourceId 7 | }), 8 | z.object({ 9 | type: z.literal('ERROR'), 10 | data: z.object({code: z.string(), message: z.string()}), 11 | }), 12 | ]) 13 | export type FrameMessage = z.infer 14 | 15 | export const defaultVeniceHost = 'https://app.venice.is' 16 | 17 | export interface GetIFrameProps { 18 | deploymentUrl?: string 19 | params?: {token?: string; displayName?: string} 20 | } 21 | 22 | export const getIFrameUrl = ({ 23 | deploymentUrl = defaultVeniceHost, 24 | params = {}, 25 | }: GetIFrameProps) => { 26 | const url = new URL('/connect', deploymentUrl) 27 | Object.entries(params).forEach(([key, value]) => { 28 | if (value) { 29 | url.searchParams.append(key, value) 30 | } 31 | }) 32 | return url.toString() 33 | } 34 | -------------------------------------------------------------------------------- /kits/connect/src/index.ts: -------------------------------------------------------------------------------- 1 | export {createVeniceClient} from '@usevenice/sdk' 2 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 3 | export * from './common' 4 | export * from './embed-react' 5 | export * from './popup' 6 | // codegen:end 7 | -------------------------------------------------------------------------------- /kits/connect/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist" 5 | }, 6 | "include": ["env.d.ts", "src/index.ts", "src/common.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /kits/sdk/.npmignore: -------------------------------------------------------------------------------- 1 | ../../.npmignore -------------------------------------------------------------------------------- /kits/sdk/createSdk.ts: -------------------------------------------------------------------------------- 1 | import type {oas30, oas31} from 'openapi3-ts' 2 | import {createClient} from '@usevenice/openapi-client' 3 | 4 | export type OpenAPISpec = oas30.OpenAPIObject | oas31.OpenAPIObject 5 | 6 | // export interface SdkTypes { 7 | // components: unknown 8 | // external: unknown 9 | // operations: unknown 10 | // paths: unknown 11 | // webhooks: unknown 12 | // } 13 | 14 | /** Get this from openapi */ 15 | export interface SdkDefinition { 16 | _types: {paths: Paths} 17 | oas: OpenAPISpec 18 | } 19 | 20 | // This is necessary because we cannot publish inferred type otherwise 21 | // @see https://share.cleanshot.com/06NvskP0 22 | export type SDK = ReturnType> & { 23 | // This should be made optional to keep the bundle size small 24 | // company should be able to opt-in for things like validation 25 | oas: OpenAPISpec 26 | } 27 | 28 | export function createSdk( 29 | sdkDef: SdkDefinition, 30 | ): SDK { 31 | const {oas} = sdkDef 32 | const client = createClient() 33 | return {...client, oas} 34 | } 35 | -------------------------------------------------------------------------------- /kits/sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/sdk", 3 | "version": "0.0.11", 4 | "private": false, 5 | "sideEffects": false, 6 | "main": "./dist/index.js", 7 | "types": "./dist/index.d.ts", 8 | "scripts": { 9 | "build": "tsc -p ./tsconfig.json", 10 | "clean": "rm -rf ./dist", 11 | "gen": "pnpm gen:schema && pnpm gen:types", 12 | "gen:schema": "NEXT_PUBLIC_SERVER_URL=https://app.venice.is npx tsx ../../apps/web/lib-server/appRouter.ts > ./venice.oas.json", 13 | "gen:types": "openapi-typescript ./venice.oas.json --output ./venice.oas.d.ts", 14 | "pub": "pnpm publish --no-git-checks --access public" 15 | }, 16 | "dependencies": { 17 | "@usevenice/openapi-client": "workspace:*", 18 | "openapi3-ts": "4.1.2", 19 | "tsx": "3.12.2" 20 | }, 21 | "devDependencies": { 22 | "openapi-typescript": "7.0.0-next.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /kits/sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | // This is a hack because otherwise when running code that imports from the 6 | // web module we get package not found issues. (such as `generate` call in the sdk) 7 | "baseUrl": "../../" 8 | }, 9 | "include": ["./index.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /kits/vdk/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './new-mapper' 3 | // codegen:end 4 | 5 | export * from '@usevenice/zod' 6 | -------------------------------------------------------------------------------- /kits/vdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/vdk", 3 | "description": "Vertical Development Kit", 4 | "dependencies": { 5 | "@trpc/server": "10.40.0", 6 | "@usevenice/types": "workspace:*", 7 | "@usevenice/zod": "workspace:*", 8 | "remeda": "1.6.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/useVenice/venice/6e94d3a04bc98bf1a02a484852751d6f2c46776e/logo.png -------------------------------------------------------------------------------- /packages/engine-backend/index.ts: -------------------------------------------------------------------------------- 1 | // import {zodInsecureDebug} from '@usevenice/util' 2 | 3 | // Make error message more understandable. But security risk... so turn me off unless debugging 4 | // if (process.env['NODE_ENV'] === 'development') { 5 | // zodInsecureDebug() 6 | // } 7 | 8 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 9 | export * from './context' 10 | export * from './events' 11 | export * from './parseWebhookRequest' 12 | export * from './router/index' 13 | export * from './services/index' 14 | export * from './types' 15 | // codegen:end 16 | 17 | export * from './services/metaService' 18 | export * from './services/kvStore' 19 | -------------------------------------------------------------------------------- /packages/engine-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/engine-backend", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": false, 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@trpc/server": "10.40.0", 9 | "@usevenice/cdk": "workspace:*", 10 | "@usevenice/util": "workspace:*", 11 | "@usevenice/zod": "workspace:*", 12 | "inngest": "^3.16.0", 13 | "zod-openapi": "2.11.0" 14 | }, 15 | "devDependencies": { 16 | "@clerk/nextjs": "4.29.3", 17 | "@lilyrose2798/trpc-openapi": "1.3.10", 18 | "@opensdks/runtime": "^0.0.16" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/engine-backend/router/_schemas.ts: -------------------------------------------------------------------------------- 1 | import {z} from '@usevenice/util' 2 | 3 | export const zListParams = z.object({ 4 | limit: z.number().optional(), 5 | offset: z.number().optional(), 6 | }) 7 | -------------------------------------------------------------------------------- /packages/engine-backend/router/publicRouter.ts: -------------------------------------------------------------------------------- 1 | import {zRaw} from '@usevenice/cdk' 2 | import {R, z} from '@usevenice/util' 3 | import {zodToOas31Schema} from '@usevenice/zod' 4 | import {publicProcedure, trpc} from './_base' 5 | 6 | export const publicRouter = trpc.router({ 7 | health: publicProcedure 8 | .meta({ 9 | openapi: { 10 | method: 'GET', 11 | path: '/health', 12 | tags: ['Internal'], 13 | summary: 'Health check', 14 | }, 15 | }) 16 | .input(z.void()) 17 | .output(z.string()) 18 | .query(() => 'Ok ' + new Date().toISOString()), 19 | getPublicEnv: publicProcedure.query(({ctx}) => 20 | R.pick(ctx.env, ['NEXT_PUBLIC_NANGO_PUBLIC_KEY']), 21 | ), 22 | getRawSchemas: publicProcedure 23 | .meta({ 24 | openapi: { 25 | method: 'GET', 26 | path: '/debug/raw-schemas', 27 | tags: ['Internal'], 28 | description: 'Get raw schemas', 29 | }, 30 | }) 31 | .input(z.void()) 32 | .output(z.unknown()) 33 | .query(() => R.mapValues(zRaw, (zodSchema) => zodToOas31Schema(zodSchema))), 34 | }) 35 | -------------------------------------------------------------------------------- /packages/engine-backend/services/NoopMetaService.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/require-await */ 2 | import type {MetaService, MetaTable} from './metaService' 3 | 4 | const noopTable: MetaTable = { 5 | get: async () => undefined, 6 | list: async () => [], 7 | set: async () => {}, 8 | delete: async () => {}, 9 | } 10 | 11 | // Consider adding a memory metaService as well 12 | // much like used to have memoryKV store 13 | export const noopMetaService: MetaService = { 14 | tables: { 15 | resource: noopTable, 16 | integration: noopTable, 17 | connector_config: noopTable, 18 | pipeline: noopTable, 19 | }, 20 | searchEndUsers: async () => [], 21 | searchIntegrations: async () => [], 22 | findPipelines: async () => [], 23 | listConnectorConfigInfos: async () => [], 24 | findResourcesMissingDefaultPipeline: async () => [], 25 | } 26 | -------------------------------------------------------------------------------- /packages/engine-frontend/index.ts: -------------------------------------------------------------------------------- 1 | // Is there any reason we can't have some of those be server components? 2 | // Buttons and cards seems that they should be able to 3 | 4 | 'use client' 5 | 6 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 7 | export * from './TRPCProvider' 8 | export * from './VeniceConnect' 9 | // codegen:end 10 | -------------------------------------------------------------------------------- /packages/engine-frontend/lib/useGetter.ts: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | /** 4 | * Used to create a callback to get the current value without re-rendering 5 | * whenever value changes... 6 | * 7 | * TODO: Move me to a separate frontend utils package... 8 | */ 9 | export function useGetter(value: T) { 10 | const ref = React.useRef(value) 11 | React.useEffect(() => { 12 | ref.current = value 13 | }, [value, ref]) 14 | return React.useCallback(() => ref.current, [ref]) 15 | } 16 | -------------------------------------------------------------------------------- /packages/engine-frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/engine-frontend", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": false, 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@nangohq/frontend": "0.33.8", 9 | "@tanstack/react-query": "*", 10 | "@trpc/client": "10.40.0", 11 | "@trpc/react-query": "10.40.0", 12 | "@trpc/server": "10.40.0", 13 | "@usevenice/cdk": "workspace:*", 14 | "@usevenice/engine-backend": "workspace:*", 15 | "@usevenice/ui": "workspace:*", 16 | "@usevenice/util": "workspace:*" 17 | }, 18 | "devDependencies": { 19 | "@types/react": "*" 20 | }, 21 | "peerDependencies": { 22 | "lucide-react": "*", 23 | "react": "*" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/meta-service-airbyte/Dockerfile.dockerignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/.next 3 | **/tests 4 | # Causes build failure, and not needed for just connectors 5 | apps/web 6 | -------------------------------------------------------------------------------- /packages/meta-service-airbyte/READMD.md: -------------------------------------------------------------------------------- 1 | # Venice on Airbyte 2 | 3 | This is an experimental package demonstrating running Venice integrations on top of Airbyte's integration 4 | -------------------------------------------------------------------------------- /packages/meta-service-airbyte/api/airbyte-api-health.oas.json: -------------------------------------------------------------------------------- 1 | {"openapi":"3.1.0","info":{"title":"Health","version":"1.0.0","description":"Programatically control Airbyte Cloud, OSS & Enterprise."},"servers":[{"url":"https://api.airbyte.com","description":"Airbyte API"}],"paths":{"/health":{"get":{"summary":"Health Check","tags":["Health"],"responses":{"200":{"description":"Successful operation"},"404":{"description":"Not found"}}}}}} -------------------------------------------------------------------------------- /packages/meta-service-airbyte/bin/yaml2json.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const {parseArgs} = require('node:util') 3 | 4 | async function readStreamToString(stream /* @type {NodeJS.ReadableStream} */) { 5 | const chunks = [] 6 | for await (const chunk of stream) { 7 | chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk) 8 | } 9 | return Buffer.concat(chunks).toString('utf8') 10 | } 11 | 12 | async function main() { 13 | const { 14 | values: {output}, 15 | } = parseArgs({options: {output: {type: 'string', short: 'o'}}}) 16 | 17 | const yaml = await readStreamToString(process.stdin) 18 | const json = JSON.stringify(require('yaml').parse(yaml), null, 2) 19 | if (output) { 20 | await require('node:fs/promises').writeFile(`${output}.json`, json) 21 | await require('node:fs/promises').writeFile(`${output}.yaml`, yaml) 22 | } else { 23 | process.stdout.write(json) 24 | } 25 | } 26 | 27 | // eslint-disable-next-line unicorn/prefer-top-level-await 28 | void main() 29 | -------------------------------------------------------------------------------- /packages/meta-service-airbyte/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx},./{text,utils}.ts"} 2 | export * from './airbyte-sdk' 3 | export * from './airbyteMetaService' 4 | export * from './makeAirbyteConnector' 5 | export * from './utils' 6 | // codegen:end 7 | -------------------------------------------------------------------------------- /packages/meta-service-airbyte/sample/configured-catalog.json: -------------------------------------------------------------------------------- 1 | { 2 | "streams": [ 3 | { 4 | "stream": { 5 | "name": "pokemon", 6 | "json_schema": {}, 7 | "supported_sync_modes": ["full_refresh"], 8 | "default_primary_key": [["id"]] 9 | }, 10 | "sync_mode": "full_refresh", 11 | "destination_sync_mode": "overwrite", 12 | "primary_key": [["id"]] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/meta-service-airbyte/sample/src-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "basePath": "/Users/tony/Code/usevenice/venice/apps/tests/__encrypted__/meta" 3 | } 4 | -------------------------------------------------------------------------------- /packages/meta-service-airbyte/utils.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'node:path' 2 | 3 | export function readJson(filepath: string): T { 4 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 5 | return require(path.resolve(process.cwd(), filepath)) 6 | } 7 | -------------------------------------------------------------------------------- /packages/meta-service-fs/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './makeFsKVStore' 3 | // codegen:end 4 | -------------------------------------------------------------------------------- /packages/meta-service-fs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/meta-service-fs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": false, 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@usevenice/cdk": "workspace:*", 9 | "@usevenice/connector-fs": "workspace:*", 10 | "@usevenice/util": "workspace:*" 11 | }, 12 | "devDependencies": { 13 | "@usevenice/engine-backend": "workspace:*" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/meta-service-postgres/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{spec,test,fixture}.{ts,tsx}"} 2 | export * from './makePostgresMetaService' 3 | // codegen:end 4 | -------------------------------------------------------------------------------- /packages/meta-service-postgres/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/meta-service-postgres", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": false, 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@usevenice/cdk": "workspace:*", 9 | "@usevenice/connector-postgres": "workspace:*", 10 | "@usevenice/util": "workspace:*" 11 | }, 12 | "devDependencies": { 13 | "@usevenice/engine-backend": "workspace:*" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/meta-service-redis/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './redisKvStore' 3 | // codegen:end 4 | -------------------------------------------------------------------------------- /packages/meta-service-redis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/meta-service-redis", 3 | "version": "0.0.0", 4 | "private": true, 5 | "sideEffects": [], 6 | "module": "./index.ts", 7 | "dependencies": { 8 | "@usevenice/cdk": "workspace:*", 9 | "@usevenice/engine-backend": "workspace:*", 10 | "@usevenice/util": "workspace:*", 11 | "handy-redis": "2.3.1", 12 | "redis": "3.1.2" 13 | }, 14 | "devDependencies": {} 15 | } 16 | -------------------------------------------------------------------------------- /packages/meta-service-redis/redisKvStore.ts: -------------------------------------------------------------------------------- 1 | import {createNodeRedisClient} from 'handy-redis' 2 | 3 | import {zKVStore} from '@usevenice/engine-backend' 4 | import {memoize, safeJSONParse, z, zFunction} from '@usevenice/util' 5 | 6 | export const makeRedisKVStore = zFunction( 7 | z.object({redisUrl: z.string().optional()}), 8 | zKVStore, 9 | ({redisUrl}) => { 10 | const redis = memoize(() => createNodeRedisClient({url: redisUrl})) 11 | return { 12 | get: (id) => 13 | redis().get(id).then(safeJSONParse) as Promise>, 14 | list: async () => { 15 | const keys = await redis().keys('*') 16 | return Promise.all( 17 | keys.map((k) => 18 | redis() 19 | .get(k) 20 | .then( 21 | (v) => 22 | [k, safeJSONParse(v) as Record] as const, 23 | ), 24 | ), 25 | ) 26 | }, 27 | set: (id, data) => 28 | redis() 29 | .set(id, JSON.stringify(data)) 30 | .then(() => {}), 31 | close: () => redis().quit(), 32 | } 33 | }, 34 | ) 35 | -------------------------------------------------------------------------------- /packages/ui/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/ui/command/index.ts: -------------------------------------------------------------------------------- 1 | // TODO: Moving commands into its own separate package. Doesn't actually have to depend on ui package 2 | // unless command-components are used as the command primitives can also be used to 3 | // power APIs and CLIs. In fact perhaps command-components should remain in ui package 4 | // while the command primitives are moved to a separate package. 5 | 6 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: ["./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"]} 7 | export * from './command-components' 8 | export * from './command-fns' 9 | export * from './command-types' 10 | // codegen:end 11 | -------------------------------------------------------------------------------- /packages/ui/components/EffectContainer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {useEffect} from 'react' 3 | 4 | export function EffectContainer({ 5 | effect, 6 | deps, 7 | children, 8 | }: { 9 | effect: () => void 10 | deps?: React.DependencyList 11 | children?: React.ReactNode 12 | }) { 13 | // eslint-disable-next-line react-hooks/exhaustive-deps 14 | useEffect(effect, deps ?? []) 15 | return <>{children} 16 | } 17 | -------------------------------------------------------------------------------- /packages/ui/components/Icon.tsx: -------------------------------------------------------------------------------- 1 | import * as lucide from 'lucide-react' 2 | 3 | export type IconName = Exclude< 4 | keyof typeof lucide, 5 | | 'default' 6 | | 'IconNode' 7 | | 'Icon' 8 | | 'createLucideIcon' 9 | | 'LucideIcon' 10 | | 'LucideProps' 11 | | `Lucide${string}` 12 | | `${string}Icon` 13 | > 14 | 15 | export function Icon(props: {name: IconName} & lucide.LucideProps) { 16 | const LucideIcon = lucide[props.name] 17 | return 18 | } 19 | -------------------------------------------------------------------------------- /packages/ui/components/Kbd.tsx: -------------------------------------------------------------------------------- 1 | import {cn} from '../utils' 2 | 3 | export function Kbd(props: { 4 | shortcut: string 5 | border?: boolean 6 | className?: string 7 | }) { 8 | return ( 9 | 15 | {props.shortcut} 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /packages/ui/components/LoadingText.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import {useIntervalEffect} from '@react-hookz/web' 4 | import React from 'react' 5 | 6 | export function LoadingText({ 7 | text = 'Loading', 8 | className, 9 | }: { 10 | text?: string 11 | className?: string 12 | }) { 13 | const [count, setCount] = React.useState(0) 14 | useIntervalEffect(() => { 15 | setCount((prev) => (prev + 1) % 3) 16 | }, INTERVAL_MS) 17 | return ( 18 | 19 | {text} 20 | {'.'.repeat(count + 1)} 21 | 22 | ) 23 | } 24 | 25 | const INTERVAL_MS = 500 26 | -------------------------------------------------------------------------------- /packages/ui/components/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: ["./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}", "./CodeEditor.tsx", "./DataGrid.tsx"]} 2 | export * from './DataTable' 3 | export * from './EffectContainer' 4 | export * from './Icon' 5 | export * from './Kbd' 6 | export * from './LoadingText' 7 | export * from './SchemaForm' 8 | export * from './SchemaSheet' 9 | // codegen:end 10 | -------------------------------------------------------------------------------- /packages/ui/domain-components/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './ConnectorCard' 3 | export * from './ResourceCard' 4 | // codegen:end 5 | -------------------------------------------------------------------------------- /packages/ui/hooks/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './useConstant' 3 | export * from './useWhyDidYouUpdate' 4 | export * from './useWithToast' 5 | // codegen:end 6 | -------------------------------------------------------------------------------- /packages/ui/hooks/useConstant.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | interface ResultBox { 4 | v: T 5 | } 6 | 7 | export function useConstant(fn: () => T): T { 8 | const ref = React.useRef>() 9 | 10 | if (!ref.current) { 11 | ref.current = {v: fn()} 12 | } 13 | 14 | return ref.current.v 15 | } 16 | -------------------------------------------------------------------------------- /packages/ui/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: [./DataGrid.tsx, ./new-components/index.ts, ./CodeEditor.tsx] } 2 | export * from './command/index' 3 | export * from './components/index' 4 | export * from './domain-components/index' 5 | export * from './hooks/index' 6 | export * from './shadcn/index' 7 | export * from './utils' 8 | // codegen:end 9 | 10 | export {Resizable} from 're-resizable' 11 | -------------------------------------------------------------------------------- /packages/ui/shadcn/Input.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import React from 'react' 4 | 5 | import {cn} from '../utils' 6 | 7 | export interface InputProps 8 | extends React.InputHTMLAttributes {} 9 | 10 | const Input = React.forwardRef( 11 | ({className, type, ...props}, ref) => ( 12 | 21 | ), 22 | ) 23 | Input.displayName = 'Input' 24 | 25 | export {Input} 26 | -------------------------------------------------------------------------------- /packages/ui/shadcn/Label.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as LabelPrimitive from '@radix-ui/react-label' 4 | import type {VariantProps} from 'class-variance-authority' 5 | import {cva} from 'class-variance-authority' 6 | import React from 'react' 7 | 8 | import {cn} from '../utils' 9 | 10 | const labelVariants = cva( 11 | 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', 12 | ) 13 | 14 | const Label = React.forwardRef< 15 | React.ElementRef, 16 | React.ComponentPropsWithoutRef & 17 | VariantProps 18 | >(({className, ...props}, ref) => ( 19 | 24 | )) 25 | Label.displayName = LabelPrimitive.Root.displayName 26 | 27 | export {Label} 28 | -------------------------------------------------------------------------------- /packages/ui/shadcn/Separator.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as SeparatorPrimitive from '@radix-ui/react-separator' 4 | import * as React from 'react' 5 | 6 | import {cn} from '../utils' 7 | 8 | const Separator = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >( 12 | ( 13 | {className, orientation = 'horizontal', decorative = true, ...props}, 14 | ref, 15 | ) => ( 16 | 27 | ), 28 | ) 29 | Separator.displayName = SeparatorPrimitive.Root.displayName 30 | 31 | export {Separator} 32 | -------------------------------------------------------------------------------- /packages/ui/shadcn/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './AlertDialog' 3 | export * from './Badge' 4 | export * from './Breadcrumb' 5 | export * from './Button' 6 | export * from './Card' 7 | export * from './Checkbox' 8 | export * from './Combobox' 9 | export * from './Command' 10 | export * from './Dialog' 11 | export * from './DropdownMenu' 12 | export * from './Input' 13 | export * from './Label' 14 | export * from './Popover' 15 | export * from './ScrollArea' 16 | export * from './Separator' 17 | export * from './Sheet' 18 | export * from './Table' 19 | export * from './Toast' 20 | export * from './Toaster' 21 | // codegen:end 22 | -------------------------------------------------------------------------------- /packages/ui/utils.ts: -------------------------------------------------------------------------------- 1 | import type {ClassValue} from 'clsx' 2 | import {clsx} from 'clsx' 3 | import React from 'react' 4 | import {twMerge} from 'tailwind-merge' 5 | 6 | /** https://ui.shadcn.com/docs/installation */ 7 | export function cn(...inputs: ClassValue[]) { 8 | return twMerge(clsx(inputs)) 9 | } 10 | 11 | export function getValidChildren(children: React.ReactNode) { 12 | return React.Children.toArray(children).filter((child) => 13 | React.isValidElement(child), 14 | ) as React.ReactElement[] 15 | } 16 | -------------------------------------------------------------------------------- /packages/util/@types/blossomfinance__iso-4217-currencies.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@blossomfinance/iso-4217-currencies' { 2 | export interface CurrencyInfo { 3 | symbol: string 4 | name: string 5 | symbolNative: string 6 | decimalDigits: number 7 | rounding: number 8 | code: string 9 | namePlural: string 10 | } 11 | 12 | export const map: Record 13 | export const codes: string[] 14 | export const currencies: CurrencyInfo[] 15 | } 16 | -------------------------------------------------------------------------------- /packages/util/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /packages/util/amount-utils.spec.ts: -------------------------------------------------------------------------------- 1 | import {AM, parseMoney} from './amount-utils' 2 | 3 | test('AmountMap equals', () => { 4 | expect(AM.equals({}, {})).toBe(true) 5 | expect(AM.equals({USD: 0}, {EUR: 0})).toBe(true) 6 | 7 | expect(AM.equals({USD: 0}, {EUR: 1})).toBe(false) 8 | 9 | expect(AM.equals({USD: 5.1234567890123456}, {USD: 5.123456789012345})).toBe( 10 | true, 11 | ) 12 | }) 13 | 14 | test.each([ 15 | ['US$12000.00', 12000], 16 | ['MX$12000.00', 12000], 17 | ['CA$12000.00', 12000], 18 | ['AU$12000.00', 12000], 19 | ])('parseMoney("%s") -> %o', (input, output) => { 20 | expect(parseMoney(input)).toEqual(output) 21 | }) 22 | -------------------------------------------------------------------------------- /packages/util/array-utils.ts: -------------------------------------------------------------------------------- 1 | import type {MaybeArray} from './type-utils' 2 | 3 | export {inPlaceSort, sort} from 'fast-sort' 4 | export {sortedIndexBy} from 'lodash' 5 | 6 | export function nonEmpty(arr: T[]) { 7 | if (arr.length === 0) { 8 | throw new Error('Expected non-empty array') 9 | } 10 | return arr as [T, ...T[]] 11 | } 12 | 13 | /** 14 | * https://stackoverflow.com/a/16436975/692499 15 | */ 16 | export function arrayEquals( 17 | a: T[], 18 | b: T[], 19 | isEqual: (a: T | undefined, b: T | undefined) => boolean = Object.is, 20 | ) { 21 | if (a === b) { 22 | return true 23 | } 24 | if (a.length !== b.length) { 25 | return false 26 | } 27 | for (let i = 0; i < a.length; ++i) { 28 | if (!isEqual(a[i], b[i])) { 29 | return false 30 | } 31 | } 32 | return true 33 | } 34 | 35 | export function fromMaybeArray(maybeArray: MaybeArray) { 36 | return Array.isArray(maybeArray) ? maybeArray : [maybeArray] 37 | } 38 | -------------------------------------------------------------------------------- /packages/util/balance-utils.ts: -------------------------------------------------------------------------------- 1 | import type {Amount, AmountMap} from '@usevenice/util' 2 | import {AM} from '@usevenice/util' 3 | 4 | export function computeTrialBalance( 5 | postings: Array<{amount?: Amount | null; date: ISODateTime | ISODate}>, 6 | ) { 7 | const balanceByDate: Record = {} 8 | const balance = AM({}) 9 | for (const posting of postings) { 10 | if (!posting.amount) { 11 | continue 12 | } 13 | AM.incrInPlace(balance, posting.amount) 14 | balanceByDate[posting.date] = AM.incrInPlace( 15 | balanceByDate[posting.date] ?? {}, 16 | posting.amount, 17 | ) 18 | } 19 | return {balanceByDate, balance} 20 | } 21 | -------------------------------------------------------------------------------- /packages/util/debug-utils.ts: -------------------------------------------------------------------------------- 1 | export function withLog(prefix = '[withLog]', input: T) { 2 | console.warn(prefix, input) 3 | return input 4 | } 5 | 6 | export function debugMe(input: T) { 7 | console.warn('[debugMe]', JSON.stringify(input, null, 2)) 8 | return input 9 | } 10 | // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any 11 | ;(globalThis as any).debugMe = debugMe 12 | ;(globalThis as any).withLog = withLog 13 | 14 | declare global { 15 | interface Window { 16 | debugMe: typeof debugMe 17 | withLog: typeof withLog 18 | } 19 | } 20 | 21 | export {default as invariant} from 'tiny-invariant' 22 | -------------------------------------------------------------------------------- /packages/util/function-utils.ts: -------------------------------------------------------------------------------- 1 | import type {MicroMemoize as Memoize} from 'micro-memoize' 2 | import memoize from 'micro-memoize' 3 | 4 | import type {AnyFunction} from './type-utils' 5 | 6 | export function memoizeBy( 7 | func: TFunc, 8 | isMatchingKey?: (prev: Parameters, next: Parameters) => boolean, 9 | opts?: Memoize.StandardOptions, 10 | ) { 11 | return memoize(func, { 12 | maxSize: Number.POSITIVE_INFINITY, 13 | isMatchingKey: isMatchingKey as Memoize.MatchingKeyComparator, 14 | ...opts, 15 | }) 16 | } 17 | 18 | export function catchAsNull(fn: () => T | null) { 19 | try { 20 | return fn() 21 | } catch { 22 | return null 23 | } 24 | } 25 | 26 | export {default as memoize} from 'micro-memoize' 27 | -------------------------------------------------------------------------------- /packages/util/http/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './http-utils' 3 | export * from './makeHttpClient' 4 | export * from './makeOpenApiClient' 5 | export * from './oauth-utils' 6 | // codegen:end 7 | -------------------------------------------------------------------------------- /packages/util/id-utils.ts: -------------------------------------------------------------------------------- 1 | import {decodeTime, ulid} from 'ulidx' 2 | 3 | export function makeUlid() { 4 | return ulid() 5 | } 6 | makeUlid.decodeTime = decodeTime 7 | 8 | // TODO: Add converter to / from uuid. 9 | // As ulid is 128-bit compatible with uuid 10 | // https://github.com/ulid/spec#universally-unique-lexicographically-sortable-identifier 11 | 12 | // MARK: - Deprecated stuff, remove me.... 13 | 14 | /** @deprecated */ 15 | export function temp_makeId

( 16 | prefix: P, 17 | externalId: string | null | undefined, 18 | ) { 19 | return `${prefix}_${externalId ?? makeUlid()}` as const 20 | } 21 | -------------------------------------------------------------------------------- /packages/util/immutable-utils.ts: -------------------------------------------------------------------------------- 1 | import {setAutoFreeze} from 'immer' 2 | 3 | // Auto-freeze is not cool... 4 | // @see https://github.com/immerjs/immer/issues/959 5 | setAutoFreeze(false) 6 | 7 | // Should this live in its own separate file? 8 | export {produce} from 'immer' // Auto-freeze is cool 9 | export type {WritableDraft} from 'immer/dist/types/types-external' // Auto-freeze is cool 10 | -------------------------------------------------------------------------------- /packages/util/injected-utils.ts: -------------------------------------------------------------------------------- 1 | import {defineProxyFn} from './di-utils' 2 | 3 | /** @deprecated */ 4 | export const $ensureDir = 5 | defineProxyFn<(path: string) => Promise>('$ensureDir') 6 | 7 | export const $fs = defineProxyFn<() => typeof import('fs/promises')>('$fs') 8 | export const $path = defineProxyFn<() => typeof import('path')>('$path') 9 | export const $chokidar = 10 | defineProxyFn<() => typeof import('chokidar')>('$chokidar') 11 | 12 | export const $execCommand = 13 | defineProxyFn< 14 | (cmd: string, stdin?: string) => Promise<{stdout: string; stderr?: string}> 15 | >('$execCommand') 16 | 17 | export const $readFile = 18 | defineProxyFn('$readFile') 19 | 20 | /** @returns void technically, false will throw */ 21 | export const $writeFile = 22 | defineProxyFn('$writeFile') 23 | 24 | export const $appendFile = 25 | defineProxyFn<(path: string, content: string) => Promise>('$appendFile') 26 | -------------------------------------------------------------------------------- /packages/util/iterable-utils.spec.ts: -------------------------------------------------------------------------------- 1 | import {isAsyncIterable, isIterable} from './iterable-utils' 2 | 3 | function* yieldNever() {} 4 | async function* asyncYieldNever() {} 5 | 6 | test('isIterable', () => { 7 | expect(isIterable({})).toBe(false) 8 | expect(isIterable(null)).toBe(false) 9 | expect(isIterable([])).toBe(true) 10 | 11 | expect(isIterable(yieldNever())).toBe(true) 12 | expect(isIterable(asyncYieldNever())).toBe(false) 13 | }) 14 | 15 | test('isAsyncIterable', () => { 16 | expect(isAsyncIterable({})).toBe(false) 17 | expect(isAsyncIterable(null)).toBe(false) 18 | expect(isAsyncIterable([])).toBe(false) 19 | 20 | expect(isAsyncIterable(yieldNever())).toBe(false) 21 | expect(isAsyncIterable(asyncYieldNever())).toBe(true) 22 | }) 23 | -------------------------------------------------------------------------------- /packages/util/iterable-utils.ts: -------------------------------------------------------------------------------- 1 | export function isAsyncIterable(input: unknown): input is AsyncIterable { 2 | return ( 3 | input != null && 4 | typeof input === 'object' && 5 | typeof (input as Record)[Symbol.asyncIterator] === 6 | 'function' 7 | ) 8 | } 9 | 10 | export function isIterable(input: unknown): input is Iterable { 11 | return ( 12 | input != null && 13 | typeof input === 'object' && 14 | typeof (input as Record)[Symbol.iterator] === 15 | 'function' 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /packages/util/json-utils.ts: -------------------------------------------------------------------------------- 1 | import type {Json} from './zod-utils' 2 | 3 | export {stringify as javascriptStringify} from 'javascript-stringify' 4 | export {default as stableStringify} from 'json-stable-stringify' 5 | export {default as compactStringify} from 'json-stringify-pretty-compact' 6 | 7 | /** @returns as Json technically. but breaks a bunch of types, so ... */ 8 | export function safeJSONParse(str: string | null | undefined) { 9 | try { 10 | return str ? (JSON.parse(str) as Json) : undefined 11 | } catch { 12 | // console.warn('Failed to parse JSON', str, err) 13 | return undefined 14 | } 15 | } 16 | 17 | export function safeJSONStringify(obj: unknown) { 18 | try { 19 | return obj === undefined ? undefined : JSON.stringify(obj) 20 | } catch { 21 | // console.warn('Failed to parse JSON', str, err) 22 | return undefined 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/util/logging-utils.ts: -------------------------------------------------------------------------------- 1 | export function makeLogger(tag?: string, data?: Record) { 2 | function wrapLogFunction( 3 | fn: (message?: unknown, ...optionalParams: unknown[]) => void, 4 | ) { 5 | return (message?: unknown, ...optionalParams: unknown[]) => { 6 | const args: unknown[] = [] 7 | if (typeof tag == 'string') { 8 | args.push(`[${tag}]`) 9 | } 10 | if (typeof message === 'string') { 11 | args.push(message) 12 | } 13 | args.push(...optionalParams) 14 | if (data) { 15 | args.push(data) 16 | } 17 | 18 | fn(...args) 19 | } 20 | } 21 | 22 | return { 23 | log: wrapLogFunction(console.log), 24 | info: wrapLogFunction(console.info), 25 | warn: wrapLogFunction(console.warn), 26 | error: wrapLogFunction(console.error), 27 | debug: wrapLogFunction(console.debug), 28 | } 29 | } 30 | 31 | export type Logger = ReturnType 32 | -------------------------------------------------------------------------------- /packages/util/perf-utils.ts: -------------------------------------------------------------------------------- 1 | export function withPerf( 2 | message: string | [string, ...unknown[]], 3 | fn: () => T, 4 | ) { 5 | const start = performance.now() 6 | const ret = fn() 7 | const end = performance.now() 8 | if (typeof process !== 'undefined' && process.env['LOG_LEVEL'] === 'warn') { 9 | return ret 10 | } 11 | if (Array.isArray(message)) { 12 | console.debug(`${message[0]} (in ${end - start}ms)`, ...message.slice(1)) 13 | } else { 14 | console.debug(`${message} (in ${end - start}ms)`) 15 | } 16 | return ret 17 | } 18 | -------------------------------------------------------------------------------- /packages/util/proxy-utils.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unsafe-call */ 2 | /* eslint-disable @typescript-eslint/no-unsafe-assignment */ 3 | /* eslint-disable @typescript-eslint/no-unsafe-member-access */ 4 | import {noopFunctionMap} from './proxy-utils' 5 | 6 | test('noopProxy', () => { 7 | const obj = noopFunctionMap() 8 | expect(obj.hello()).toEqual(undefined) 9 | expect(typeof obj.anything).toEqual('function') 10 | }) 11 | -------------------------------------------------------------------------------- /packages/util/proxy-utils.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | export function noopFunctionMap() { 3 | return new Proxy({}, {get: () => () => undefined}) as T 4 | } 5 | -------------------------------------------------------------------------------- /packages/util/schrono/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './MPDate' 3 | export * from './MPInterval' 4 | export * from './schrono-utils' 5 | export * from './simple-duration' 6 | export * from './simple-schedule' 7 | // codegen:end 8 | -------------------------------------------------------------------------------- /packages/util/schrono/simple-duration.spec.ts: -------------------------------------------------------------------------------- 1 | import {parseDurationExpression} from './simple-duration' 2 | 3 | describe('Duration expressions', () => { 4 | test('parseDurationExpression integer', () => { 5 | expect(parseDurationExpression('2 weeks')?.toObject()).toEqual({weeks: 2}) 6 | }) 7 | 8 | test('parseDurationExpression decimal', () => { 9 | expect(parseDurationExpression('2.5 months')?.toObject()).toEqual({ 10 | months: 2.5, 11 | }) 12 | }) 13 | 14 | test('parse duration assumes days', () => { 15 | expect(parseDurationExpression('5')?.toObject()).toEqual({days: 5}) 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /packages/util/schrono/simple-duration.ts: -------------------------------------------------------------------------------- 1 | import {Duration} from 'luxon' 2 | 3 | // MARK: - Duration expressions 4 | 5 | const DURATION_REGEX = /([\d.]+)\s*(day|week|month|quarter|year)?s?/i 6 | export function parseDurationExpression( 7 | input?: string | null, 8 | ): Duration | null { 9 | if (!input) { 10 | return null 11 | } 12 | 13 | const [, rawQuantity, unit = 'day'] = input.match(DURATION_REGEX) ?? [] 14 | const quantity = rawQuantity ? Number.parseFloat(rawQuantity) : null 15 | 16 | if (quantity == null || Number.isNaN(quantity) || !unit) { 17 | return null 18 | } 19 | 20 | return Duration.fromObject({[unit]: quantity}) 21 | } 22 | -------------------------------------------------------------------------------- /packages/util/string-utils.spec.ts: -------------------------------------------------------------------------------- 1 | import {pluralize, startCase} from './string-utils' 2 | 3 | test('startCase converts / to space', () => { 4 | expect(startCase('credit/credit card')).toBe('Credit Credit Card') 5 | }) 6 | 7 | test('startCase preserves uppercase', () => { 8 | expect(startCase('credit/CREDIT_CARD')).toBe('Credit CREDIT CARD') 9 | }) 10 | 11 | test.each<[number, string, string]>([ 12 | [100, 'Session', 'Sessions'], 13 | [100, 'USD', 'USDS'], 14 | [100, 'thesis', 'theses'], 15 | [1.3, 'thesis', 'theses'], 16 | [0.5, 'thesis', 'theses'], 17 | [0, 'thesis', 'theses'], 18 | [1, 'thesis', 'thesis'], 19 | [-1, 'thesis', 'theses'], 20 | ])('pluraize (%p, %p) -> %p', (num, word, output) => { 21 | expect(pluralize(word, num)).toEqual(output) 22 | }) 23 | -------------------------------------------------------------------------------- /packages/util/string-utils.ts: -------------------------------------------------------------------------------- 1 | import {startCase, camelCase as _camelCase} from 'lodash' 2 | import type {CamelCase} from 'type-fest' 3 | 4 | export { 5 | padStart as leftPad, 6 | snakeCase, 7 | startCase, 8 | upperFirst as upperCaseFirst, 9 | } from 'lodash' 10 | export {default as md5Hash} from 'md5-hex' 11 | export {default as pluralize} from 'pluralize' 12 | export {sentenceCase} from 'sentence-case' 13 | 14 | /** Adapted from https://github.com/esamattis/underscore.string/blob/master/titleize.js */ 15 | export function titleCase(str: string | undefined) { 16 | return startCase(str) 17 | .toLowerCase() 18 | .replace(/(?:^|\s|-)\S/g, (c) => c.toUpperCase()) 19 | } 20 | 21 | export function camelCase(str: T) { 22 | return _camelCase(str) as CamelCase 23 | } 24 | -------------------------------------------------------------------------------- /patches/@stoplight__elements-core@7.7.10.patch: -------------------------------------------------------------------------------- 1 | diff --git a/index.mjs b/index.mjs 2 | index d2a250bdb64b330ccb0c98070c952afe6767268a..d5a085c0d8fe36da3d7c119a77ea519f1f294837 100644 3 | --- a/index.mjs 4 | +++ b/index.mjs 5 | @@ -1931,7 +1931,9 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe 6 | }); 7 | let response; 8 | try { 9 | - response = yield fetch(...request); 10 | + // HACK to allow intercepting fetch requests to instead go through to the passthrough api 11 | + const _fetch = globalThis._stoplight_fetch ?? fetch 12 | + response = yield _fetch(...request); 13 | } 14 | catch (e) { 15 | setResponse({ error: new NetworkError(e.message) }); 16 | -------------------------------------------------------------------------------- /patches/cac@6.7.12.patch: -------------------------------------------------------------------------------- 1 | diff --git a/dist/index.js b/dist/index.js 2 | index 017d3a4..8bccef6 100644 3 | --- a/dist/index.js 4 | +++ b/dist/index.js 5 | @@ -16,6 +16,13 @@ function toVal(out, key, val, opts) { 6 | : (x = +val,x * 0 === 0) ? x : val 7 | ); 8 | out[key] = old == null ? nxt : (Array.isArray(old) ? old.concat(nxt) : [old, nxt]); 9 | + 10 | + // HACK to fix CAC parsing string as number and truncating precision 11 | + // e.g. '525323154705352826' -> 525323154705352800 causing problem things like SaltEdgeClient 12 | + // @see https://github.com/cacjs/cac/issues/23 13 | + if (typeof out[key] === 'number' && String(out[key]) !== val) { 14 | + out[key] = val 15 | + } 16 | } 17 | 18 | function mri2 (args, opts) { 19 | -------------------------------------------------------------------------------- /patches/typescript@4.8.2.patch: -------------------------------------------------------------------------------- 1 | diff --git a/lib/tsserver.js b/lib/tsserver.js 2 | index 481cb5866634edf6d8c82fc9f0e272ce5268c4de..f2fa4dbe84349f5d05a56a6655d0f27b9b711786 100644 3 | --- a/lib/tsserver.js 4 | +++ b/lib/tsserver.js 5 | @@ -14335,7 +14335,7 @@ var ts; 6 | (function (ts) { 7 | ts.resolvingEmptyArray = []; 8 | ts.externalHelpersModuleNameText = "tslib"; 9 | - ts.defaultMaximumTruncationLength = 160; 10 | + ts.defaultMaximumTruncationLength = 16000; // patch for https://github.com/microsoft/TypeScript/issues/35601 11 | ts.noTruncationMaximumTruncationLength = 1000000; 12 | function getDeclarationOfKind(symbol, kind) { 13 | var declarations = symbol.declarations; -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'apps/*' 3 | - 'packages/*' 4 | - 'connectors/*' 5 | - 'verticals/*' 6 | - 'kits/*' 7 | - 'utils/*' 8 | - 'docs/' 9 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('prettier').Config} 3 | */ 4 | module.exports = { 5 | arrowParens: 'always', 6 | bracketSameLine: true, 7 | bracketSpacing: false, 8 | importOrder: [ 9 | '^node:(.+)$', 10 | '', 11 | '^@usevenice/(.+)$', 12 | '^@/(.+)$', 13 | '^[./]', 14 | ], 15 | jsxSingleQuote: false, 16 | plugins: [ 17 | // This plugin breaks on makeSyncEngine.ts... So commenting out for now. 18 | require.resolve('@ianvs/prettier-plugin-sort-imports'), 19 | require.resolve('prettier-plugin-packagejson'), 20 | require.resolve('prettier-plugin-tailwindcss'), // needs to come last 21 | ], 22 | printWidth: 80, 23 | quoteProps: 'as-needed', 24 | semi: false, 25 | singleQuote: true, 26 | tabWidth: 2, 27 | tailwindConfig: './apps/web/tailwind.config.ts', 28 | trailingComma: 'all', 29 | useTabs: false, 30 | } 31 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "pipeline": { 4 | "download": { 5 | "outputs": ["*.oas.json"] 6 | }, 7 | "generate": { 8 | "dependsOn": ["^generate", "download"], 9 | "cache": false, 10 | "outputs": ["*.oas.d.ts"] 11 | }, 12 | "clean": {}, 13 | "build": { 14 | "dependsOn": ["^build", "clean"], 15 | "cache": false 16 | }, 17 | "pub": {"cache": false, "dependsOn": ["build"]} 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /utils/env/index.ts: -------------------------------------------------------------------------------- 1 | import {createEnv} from '@t3-oss/env-core' 2 | 3 | import {z} from '@usevenice/zod' 4 | 5 | export function getEnv( 6 | name: string, 7 | schema?: T, 8 | ): z.infer { 9 | const env = createEnv({ 10 | server: {[name]: schema ?? z.string()}, 11 | runtimeEnv: process.env, 12 | }) 13 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return 14 | return env[name] 15 | } 16 | 17 | export {z} 18 | -------------------------------------------------------------------------------- /utils/env/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/env", 3 | "version": "0.0.0", 4 | "private": false, 5 | "sideEffects": false, 6 | "module": "./index.ts", 7 | "scripts": { 8 | "build": "tsc", 9 | "clean": "rm -rf dist" 10 | }, 11 | "dependencies": { 12 | "@t3-oss/env-core": "0.7.1", 13 | "@usevenice/zod": "workspace:*" 14 | }, 15 | "devDependencies": {} 16 | } 17 | -------------------------------------------------------------------------------- /utils/env/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist" 5 | }, 6 | "include": ["./index.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /utils/openapi-client/.npmignore: -------------------------------------------------------------------------------- 1 | ../../.npmignore -------------------------------------------------------------------------------- /utils/openapi-client/index.ts: -------------------------------------------------------------------------------- 1 | // Do not but any other logic in this file, which is only used to re-export from 2 | // src/index so that code compiles inside the monorepo without building 3 | export * from './src/index' 4 | -------------------------------------------------------------------------------- /utils/openapi-client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/openapi-client", 3 | "version": "0.0.2", 4 | "private": false, 5 | "sideEffects": false, 6 | "main": "./dist/index.js", 7 | "types": "./dist/index.d.ts", 8 | "scripts": { 9 | "build": "tsc -p ./tsconfig.json", 10 | "clean": "rm -rf ./dist", 11 | "pub": "pnpm publish --no-git-checks --access public" 12 | }, 13 | "dependencies": { 14 | "openapi-fetch": "0.8.1", 15 | "openapi-typescript-helpers": "0.0.4" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /utils/openapi-client/src/HTTPError.ts: -------------------------------------------------------------------------------- 1 | import type {FetchResponse} from 'openapi-fetch' 2 | 3 | export type HTTPMethod = 4 | | 'GET' 5 | | 'PUT' 6 | | 'POST' 7 | | 'DELETE' 8 | | 'OPTIONS' 9 | | 'HEAD' 10 | | 'PATCH' 11 | | 'TRACE' 12 | 13 | export class HTTPError extends Error { 14 | override name = 'HTTPError' 15 | readonly method: HTTPMethod 16 | readonly error: Extract, {error: unknown}>['error'] 17 | readonly response: FetchResponse['response'] 18 | 19 | get code() { 20 | return this.response?.status 21 | } 22 | 23 | constructor({ 24 | method, 25 | error, 26 | response: r, 27 | }: Extract, {error: unknown}> & {method: HTTPMethod}) { 28 | super(`[${r.status} ${r.statusText}] ${method.toUpperCase()} ${r.url}`) 29 | this.method = method 30 | this.error = error 31 | this.response = r 32 | Object.setPrototypeOf(this, HTTPError.prototype) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /utils/openapi-client/src/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node,bootstrap}.{ts,tsx}"} 2 | export * from './createClient' 3 | export * from './createOauthClient' 4 | export * from './HTTPError' 5 | // codegen:end 6 | -------------------------------------------------------------------------------- /utils/openapi-client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist" 5 | }, 6 | "include": ["src/*"] 7 | } 8 | -------------------------------------------------------------------------------- /utils/types/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{spec,test,fixture,d}.{ts,tsx}"} 2 | export * from './PathsOf' 3 | // codegen:end 4 | 5 | // TODO: Move these into a proper util package 6 | 7 | /** This will break for all the `unknown` unfortunately. But it is desired to remove `[k: string]: unknown` */ 8 | export type StrictKeyOf = keyof { 9 | [k in keyof T as unknown extends T[k] ? never : k]: never 10 | } 11 | export type StrictObj = Pick< 12 | T, 13 | StrictKeyOf extends keyof T ? StrictKeyOf : never 14 | > 15 | 16 | // TODO: Gotta fix this to work with PathsOf aka nested keys 17 | // Also move this into a separate types package 18 | export type ExtractKeyOfValueType = Extract< 19 | keyof { 20 | [k in keyof T as T[k] extends V ? k : never]: T[k] 21 | }, 22 | string 23 | > 24 | -------------------------------------------------------------------------------- /utils/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/types", 3 | "version": "0.0.0", 4 | "private": false, 5 | "sideEffects": false, 6 | "module": "./index.ts", 7 | "scripts": { 8 | "build": "tsc", 9 | "clean": "rm -rf dist" 10 | }, 11 | "dependencies": { 12 | "type-fest": "4.8.2" 13 | }, 14 | "devDependencies": {} 15 | } 16 | -------------------------------------------------------------------------------- /utils/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist" 5 | }, 6 | "include": ["./index.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /utils/zod/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/zod", 3 | "version": "0.0.0", 4 | "private": false, 5 | "sideEffects": false, 6 | "module": "./index.ts", 7 | "scripts": { 8 | "build": "tsc", 9 | "clean": "rm -rf dist" 10 | }, 11 | "dependencies": { 12 | "zod": "3.22.4", 13 | "zod-openapi": "2.11.0" 14 | }, 15 | "devDependencies": {} 16 | } 17 | -------------------------------------------------------------------------------- /utils/zod/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist" 5 | }, 6 | "include": ["./index.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /verticals/vertical-accounting/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './accounting' 3 | // codegen:end 4 | -------------------------------------------------------------------------------- /verticals/vertical-accounting/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/vertical-accounting", 3 | "dependencies": { 4 | "@usevenice/vdk": "workspace:*" 5 | }, 6 | "devDependencies": { 7 | "@usevenice/connector-qbo": "workspace:*" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /verticals/vertical-banking/adapters/qbo-adapter.ts: -------------------------------------------------------------------------------- 1 | import type {QBOSDK, QBOSDKTypes} from '@usevenice/connector-qbo' 2 | import type {StrictObj} from '@usevenice/vdk' 3 | import {mapper, z, zCast} from '@usevenice/vdk' 4 | import type {VerticalBanking} from '../banking' 5 | import {zBanking} from '../banking' 6 | 7 | type QBO = QBOSDKTypes['oas']['components']['schemas'] 8 | 9 | const mappers = { 10 | category: mapper( 11 | zCast>(), 12 | zBanking.category.extend({_raw: z.unknown().optional()}), 13 | { 14 | id: 'Id', 15 | name: 'FullyQualifiedName', 16 | _raw: (a) => a, 17 | }, 18 | ), 19 | } 20 | 21 | export const qboAdapter = { 22 | listCategories: async ({instance}) => { 23 | const res = await instance.query( 24 | // QBO API does not support OR in SQL query... 25 | "SELECT * FROM Account WHERE Classification IN ('Revenue', 'Expense') MAXRESULTS 1000", 26 | ) 27 | return { 28 | hasNextPage: false, 29 | items: (res.Account ?? []).map(mappers.category), 30 | } 31 | }, 32 | } satisfies VerticalBanking<{instance: QBOSDK}> 33 | -------------------------------------------------------------------------------- /verticals/vertical-banking/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './banking' 3 | // codegen:end 4 | export * from './adapters/qbo-adapter' 5 | export * from './adapters/xero-adapter' 6 | -------------------------------------------------------------------------------- /verticals/vertical-banking/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/vertical-banking", 3 | "dependencies": { 4 | "@usevenice/cdk": "workspace:*", 5 | "@usevenice/vdk": "workspace:*", 6 | "rxjs": "7.5.6" 7 | }, 8 | "devDependencies": { 9 | "@usevenice/connector-plaid": "workspace:*", 10 | "@usevenice/connector-postgres": "workspace:*", 11 | "@usevenice/connector-qbo": "workspace:*", 12 | "@usevenice/connector-xero": "workspace:*", 13 | "@usevenice/types": "workspace:*" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /verticals/vertical-investment/index.ts: -------------------------------------------------------------------------------- 1 | // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"} 2 | export * from './investment' 3 | // codegen:end 4 | -------------------------------------------------------------------------------- /verticals/vertical-investment/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/vertical-investment", 3 | "dependencies": { 4 | "@usevenice/vdk": "workspace:*" 5 | }, 6 | "devDependencies": { 7 | "@usevenice/connector-plaid": "workspace:*" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /verticals/vertical-pta/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/vertical-pta", 3 | "dependencies": { 4 | "@usevenice/vdk": "workspace:*" 5 | }, 6 | "devDependencies": { 7 | "@usevenice/connector-qbo": "workspace:*" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /verticals/vertical-sales-engagement/adapters/apollo-adapter.ts: -------------------------------------------------------------------------------- 1 | import type {ApolloSDK, ApolloSDKTypes} from '@usevenice/connector-apollo' 2 | import type {StrictObj} from '@usevenice/vdk' 3 | import {mapper, zCast} from '@usevenice/vdk' 4 | import type {VerticalSalesEngagement} from '../sales-engagement' 5 | import {zSalesEngagement} from '../sales-engagement' 6 | 7 | type Apollo = ApolloSDKTypes['oas']['components']['schemas'] 8 | 9 | const mappers = { 10 | contact: mapper( 11 | zCast>(), 12 | zSalesEngagement.contact, 13 | { 14 | id: 'id', 15 | first_name: (c) => c.first_name ?? '', 16 | last_name: (c) => c.last_name ?? '', 17 | }, 18 | ), 19 | } 20 | 21 | export const apolloAdapter = { 22 | listContacts: async ({instance}) => { 23 | const res = await instance.POST('/v1/contacts/search', {}) 24 | return { 25 | hasNextPage: true, 26 | items: res.data.contacts.map(mappers.contact), 27 | } 28 | }, 29 | } satisfies VerticalSalesEngagement<{instance: ApolloSDK}> 30 | -------------------------------------------------------------------------------- /verticals/vertical-sales-engagement/adapters/outreach-adapter.ts: -------------------------------------------------------------------------------- 1 | import type {OutreachSDK, OutreachSDKTypes} from '@usevenice/connector-outreach' 2 | import type {StrictObj} from '@usevenice/vdk' 3 | import {mapper, zCast} from '@usevenice/vdk' 4 | import type {VerticalSalesEngagement} from '../sales-engagement' 5 | import {zSalesEngagement} from '../sales-engagement' 6 | 7 | type Outreach = OutreachSDKTypes['oas']['components']['schemas'] 8 | 9 | const mappers = { 10 | contact: mapper( 11 | zCast>(), 12 | zSalesEngagement.contact, 13 | { 14 | id: (r) => r.id?.toString() ?? '', 15 | first_name: (r) => r.attributes?.firstName ?? '', 16 | last_name: (r) => r.attributes?.lastName ?? '', 17 | }, 18 | ), 19 | } 20 | 21 | export const outreachAdapter = { 22 | listContacts: async ({instance}) => { 23 | const res = await instance.GET('/prospects', {}) 24 | return {hasNextPage: true, items: res.data.data?.map(mappers.contact) ?? []} 25 | }, 26 | } satisfies VerticalSalesEngagement<{instance: OutreachSDK}> 27 | -------------------------------------------------------------------------------- /verticals/vertical-sales-engagement/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sales-engagement' 2 | export * from './adapters/apollo-adapter' 3 | export * from './adapters/outreach-adapter' 4 | export * from './adapters/salesloft-adapter' 5 | -------------------------------------------------------------------------------- /verticals/vertical-sales-engagement/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@usevenice/vertical-sales-engagement", 3 | "dependencies": { 4 | "@usevenice/vdk": "workspace:*" 5 | }, 6 | "devDependencies": { 7 | "@usevenice/connector-apollo": "workspace:*", 8 | "@usevenice/connector-outreach": "workspace:*", 9 | "@usevenice/connector-salesloft": "workspace:*" 10 | } 11 | } 12 | --------------------------------------------------------------------------------