├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md ├── dependabot.yml └── workflows │ ├── auth-end-to-end-tests.yml │ ├── auth-ui-end-to-end-tests.yml │ ├── federation-tests.yml │ ├── fuzzy-tests.yml │ ├── jira-linker.yml │ ├── mysql-end-to-end-tests.yml │ ├── other-end-to-end-tests.yml │ ├── postgres-end-to-end-tests.yml │ ├── publish.yml │ ├── rest-ui-end-to-end-tests.yml │ ├── sqlite-end-to-end-tests.yml │ ├── storage-provider-end-to-end-tests.yml │ ├── unit-tests.yml │ └── windows-end-to-end-tests.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .sonarcloud.properties ├── .vscode ├── launch.json └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── SECURITY.md ├── docs └── README.md ├── graphweaver.code-workspace └── src ├── .gitignore ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── clean.sh ├── eslint.config.mjs ├── examples ├── auth-zero │ ├── .env.example │ ├── README.md │ ├── databases │ │ ├── database.sql │ │ └── database.sqlite │ ├── graphweaver-config.js │ ├── package.json │ ├── src │ │ ├── admin-ui │ │ │ └── custom-pages │ │ │ │ ├── index.tsx │ │ │ │ └── welcome-page │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ ├── backend │ │ │ ├── auth │ │ │ │ ├── auth-zero.ts │ │ │ │ └── index.ts │ │ │ ├── database.ts │ │ │ ├── entities │ │ │ │ ├── index.ts │ │ │ │ └── sqlite │ │ │ │ │ ├── album.ts │ │ │ │ │ ├── artist.ts │ │ │ │ │ ├── customer.ts │ │ │ │ │ ├── employee.ts │ │ │ │ │ ├── genre.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── invoice-line.ts │ │ │ │ │ ├── invoice.ts │ │ │ │ │ ├── media-type.ts │ │ │ │ │ ├── playlist.ts │ │ │ │ │ └── track.ts │ │ │ ├── index.ts │ │ │ └── schema │ │ │ │ ├── album.ts │ │ │ │ ├── artist.ts │ │ │ │ ├── customer.ts │ │ │ │ ├── employee.ts │ │ │ │ ├── genre.ts │ │ │ │ ├── index.ts │ │ │ │ ├── invoice-line.ts │ │ │ │ ├── invoice.ts │ │ │ │ ├── media-type.ts │ │ │ │ ├── playlist.ts │ │ │ │ └── track.ts │ │ ├── css-modules.d.ts │ │ ├── frontend │ │ │ └── types.generated.ts │ │ └── types.generated.ts │ └── tsconfig.json ├── aws-cognito │ ├── .env.example │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── package.json │ ├── src │ │ ├── admin-ui │ │ │ └── custom-pages │ │ │ │ ├── index.tsx │ │ │ │ └── welcome-page │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ ├── backend │ │ │ └── index.ts │ │ ├── css-modules.d.ts │ │ ├── frontend │ │ │ └── types.generated.ts │ │ └── types.generated.ts │ └── tsconfig.json ├── databases │ ├── .env.example │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── package.json │ ├── src │ │ ├── admin-ui │ │ │ └── custom-pages │ │ │ │ ├── index.tsx │ │ │ │ └── welcome-page │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ ├── backend │ │ │ ├── database.ts │ │ │ ├── entities │ │ │ │ ├── index.ts │ │ │ │ ├── mysql │ │ │ │ │ ├── index.ts │ │ │ │ │ └── task.ts │ │ │ │ └── postgresql │ │ │ │ │ ├── index.ts │ │ │ │ │ └── user.ts │ │ │ ├── index.ts │ │ │ └── schema │ │ │ │ ├── index.ts │ │ │ │ ├── task.ts │ │ │ │ └── user.ts │ │ ├── css-modules.d.ts │ │ ├── frontend │ │ │ └── types.generated.ts │ │ └── types.generated.ts │ └── tsconfig.json ├── federation │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── integration │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── docker-compose.yaml │ │ ├── integration-test.js │ │ └── package.json │ ├── package.json │ ├── src │ │ ├── backend │ │ │ ├── data.ts │ │ │ ├── index.ts │ │ │ └── schema │ │ │ │ ├── case-study.ts │ │ │ │ ├── deprecated-product.ts │ │ │ │ ├── hidden-entity.ts │ │ │ │ ├── index.ts │ │ │ │ ├── inventory.ts │ │ │ │ ├── non-resolvable-entity.ts │ │ │ │ ├── product-dimension.ts │ │ │ │ ├── product-research.ts │ │ │ │ ├── product-variation.ts │ │ │ │ ├── product.ts │ │ │ │ └── user.ts │ │ ├── frontend │ │ │ └── types.generated.ts │ │ └── types.generated.ts │ └── tsconfig.json ├── microsoft-entra │ ├── .env.example │ ├── README.md │ ├── databases │ │ ├── database.sql │ │ └── database.sqlite │ ├── graphweaver-config.js │ ├── package.json │ ├── src │ │ ├── admin-ui │ │ │ └── custom-pages │ │ │ │ ├── index.tsx │ │ │ │ └── welcome-page │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ ├── backend │ │ │ ├── auth │ │ │ │ ├── index.ts │ │ │ │ └── microsoft-entra.ts │ │ │ ├── database.ts │ │ │ ├── entities │ │ │ │ ├── index.ts │ │ │ │ └── sqlite │ │ │ │ │ ├── album.ts │ │ │ │ │ ├── artist.ts │ │ │ │ │ ├── customer.ts │ │ │ │ │ ├── employee.ts │ │ │ │ │ ├── genre.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── invoice-line.ts │ │ │ │ │ ├── invoice.ts │ │ │ │ │ ├── media-type.ts │ │ │ │ │ ├── playlist.ts │ │ │ │ │ └── track.ts │ │ │ ├── index.ts │ │ │ └── schema │ │ │ │ ├── album.ts │ │ │ │ ├── artist.ts │ │ │ │ ├── customer.ts │ │ │ │ ├── employee.ts │ │ │ │ ├── genre.ts │ │ │ │ ├── index.ts │ │ │ │ ├── invoice-line.ts │ │ │ │ ├── invoice.ts │ │ │ │ ├── media-type.ts │ │ │ │ ├── playlist.ts │ │ │ │ └── track.ts │ │ ├── css-modules.d.ts │ │ ├── frontend │ │ │ └── types.generated.ts │ │ └── types.generated.ts │ └── tsconfig.json ├── okta │ ├── .env.example │ ├── README.md │ ├── databases │ │ ├── database.sql │ │ └── database.sqlite │ ├── graphweaver-config.js │ ├── package.json │ ├── src │ │ ├── admin-ui │ │ │ └── custom-pages │ │ │ │ ├── index.tsx │ │ │ │ └── welcome-page │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ ├── backend │ │ │ ├── auth │ │ │ │ ├── index.ts │ │ │ │ └── okta.ts │ │ │ ├── database.ts │ │ │ ├── entities │ │ │ │ ├── index.ts │ │ │ │ └── sqlite │ │ │ │ │ ├── album.ts │ │ │ │ │ ├── artist.ts │ │ │ │ │ ├── customer.ts │ │ │ │ │ ├── employee.ts │ │ │ │ │ ├── genre.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── invoice-line.ts │ │ │ │ │ ├── invoice.ts │ │ │ │ │ ├── media-type.ts │ │ │ │ │ ├── playlist.ts │ │ │ │ │ └── track.ts │ │ │ ├── index.ts │ │ │ └── schema │ │ │ │ ├── album.ts │ │ │ │ ├── artist.ts │ │ │ │ ├── customer.ts │ │ │ │ ├── employee.ts │ │ │ │ ├── genre.ts │ │ │ │ ├── index.ts │ │ │ │ ├── invoice-line.ts │ │ │ │ ├── invoice.ts │ │ │ │ ├── media-type.ts │ │ │ │ ├── playlist.ts │ │ │ │ └── track.ts │ │ ├── css-modules.d.ts │ │ ├── frontend │ │ │ └── types.generated.ts │ │ └── types.generated.ts │ └── tsconfig.json ├── rest-with-auth │ ├── .env.example │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── database.sql │ ├── graphweaver-config.js │ ├── package.json │ ├── scripts │ │ └── import.sh │ ├── src │ │ ├── admin-ui │ │ │ ├── custom-fields │ │ │ │ ├── index.ts │ │ │ │ └── link.tsx │ │ │ └── custom-pages │ │ │ │ ├── index.tsx │ │ │ │ └── welcome-page │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ ├── backend │ │ │ ├── auth │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── methods │ │ │ │ │ ├── api-key.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── magic-link.ts │ │ │ │ │ ├── one-time-password.ts │ │ │ │ │ ├── passkey.ts │ │ │ │ │ ├── password.ts │ │ │ │ │ └── web3.ts │ │ │ │ └── roles.ts │ │ │ ├── database.ts │ │ │ ├── entities │ │ │ │ ├── index.ts │ │ │ │ └── mysql │ │ │ │ │ ├── api-key.ts │ │ │ │ │ ├── authentication.ts │ │ │ │ │ ├── credential.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── tag.ts │ │ │ │ │ ├── task-count-by-tag.ts │ │ │ │ │ ├── task.ts │ │ │ │ │ └── trace.ts │ │ │ ├── index.ts │ │ │ ├── schema │ │ │ │ ├── index.ts │ │ │ │ ├── tag.ts │ │ │ │ ├── task-count-by-tag.ts │ │ │ │ ├── task.ts │ │ │ │ ├── trace.ts │ │ │ │ └── user.ts │ │ │ └── utils.ts │ │ ├── frontend │ │ │ └── types.generated.ts │ │ └── types.generated.ts │ ├── tsconfig.json │ └── types.generated.ts ├── rest │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── package.json │ ├── src │ │ ├── backend │ │ │ ├── index.ts │ │ │ ├── schema │ │ │ │ ├── index.ts │ │ │ │ ├── person.ts │ │ │ │ └── vehicle.ts │ │ │ └── utils.ts │ │ ├── frontend │ │ │ └── types.generated.ts │ │ └── types.generated.ts │ └── tsconfig.json ├── s3-storage │ ├── .env.example │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── database.sql │ ├── package.json │ ├── scripts │ │ └── import.sh │ ├── src │ │ ├── admin-ui │ │ │ └── custom-pages │ │ │ │ ├── index.tsx │ │ │ │ └── welcome-page │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ ├── backend │ │ │ ├── custom-mutations │ │ │ │ └── index.ts │ │ │ ├── custom-queries │ │ │ │ └── index.ts │ │ │ ├── database.ts │ │ │ ├── entities │ │ │ │ ├── index.ts │ │ │ │ └── postgresql │ │ │ │ │ ├── image-note.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── submission.ts │ │ │ ├── index.ts │ │ │ ├── s3-provider.ts │ │ │ └── schema │ │ │ │ ├── image-note.ts │ │ │ │ ├── index.ts │ │ │ │ └── submission.ts │ │ ├── css-modules.d.ts │ │ ├── frontend │ │ │ └── types.generated.ts │ │ └── types.generated.ts │ └── tsconfig.json ├── sqlite │ ├── README.md │ ├── databases │ │ ├── database.sql │ │ ├── database.sqlite │ │ └── trace.sqlite │ ├── package.json │ ├── src │ │ ├── admin-ui │ │ │ ├── .gitignore │ │ │ ├── csv-export-overrides.ts │ │ │ └── custom-pages │ │ │ │ ├── dashboard │ │ │ │ ├── component.tsx │ │ │ │ ├── genre-popularity │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── graphql.generated.ts │ │ │ │ │ ├── graphql.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── styles.module.css │ │ │ │ │ └── utils.ts │ │ │ │ ├── index.ts │ │ │ │ ├── sales-over-time-per-employee │ │ │ │ │ ├── bar-chart │ │ │ │ │ │ ├── component.tsx │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── utils.ts │ │ │ │ │ ├── bar-controls │ │ │ │ │ │ ├── component.tsx │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── styles.module.css │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── line-chart │ │ │ │ │ │ ├── component.tsx │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── utils.ts │ │ │ │ │ ├── line-controls │ │ │ │ │ │ ├── component.tsx │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── styles.module.css │ │ │ │ │ ├── styles.module.css │ │ │ │ │ ├── use-data │ │ │ │ │ │ ├── graphql.generated.ts │ │ │ │ │ │ ├── graphql.ts │ │ │ │ │ │ ├── hook.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── utils.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── styles.module.css │ │ │ │ └── utils.ts │ │ │ │ ├── index.tsx │ │ │ │ └── welcome-page │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ ├── backend │ │ │ ├── database.ts │ │ │ ├── entities │ │ │ │ ├── index.ts │ │ │ │ └── sqlite │ │ │ │ │ ├── album.ts │ │ │ │ │ ├── artist.ts │ │ │ │ │ ├── customer.ts │ │ │ │ │ ├── employee.ts │ │ │ │ │ ├── genre.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── invoice-line.ts │ │ │ │ │ ├── invoice.ts │ │ │ │ │ ├── media-type.ts │ │ │ │ │ ├── playlist.ts │ │ │ │ │ ├── total-invoices-by-customer.ts │ │ │ │ │ ├── trace.ts │ │ │ │ │ └── track.ts │ │ │ ├── index.ts │ │ │ └── schema │ │ │ │ ├── album.ts │ │ │ │ ├── artist.ts │ │ │ │ ├── customer.ts │ │ │ │ ├── employee.ts │ │ │ │ ├── genre.ts │ │ │ │ ├── index.ts │ │ │ │ ├── invoice-line.ts │ │ │ │ ├── invoice.ts │ │ │ │ ├── media-type.ts │ │ │ │ ├── playlist.ts │ │ │ │ ├── total-invoices-by-customer.ts │ │ │ │ └── track.ts │ │ ├── css-modules.d.ts │ │ ├── frontend │ │ │ └── types.generated.ts │ │ └── types.generated.ts │ └── tsconfig.json └── xero │ ├── .env.example │ ├── .eslintrc.js │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── package.json │ ├── src │ ├── admin-ui │ │ └── custom-pages │ │ │ ├── dashboards │ │ │ ├── all-companies │ │ │ │ ├── component.generated.ts │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── styles.module.css │ │ │ │ └── tooltips.tsx │ │ │ ├── index.ts │ │ │ ├── single-company │ │ │ │ ├── component.generated.ts │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── styles.module.css │ │ │ │ └── tooltip.tsx │ │ │ └── theme.ts │ │ │ ├── index.generated.ts │ │ │ ├── index.tsx │ │ │ ├── welcome-page │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ │ └── xero-auth-code-receiver.tsx │ ├── backend │ │ ├── index.ts │ │ ├── schema │ │ │ ├── account.ts │ │ │ ├── index.ts │ │ │ ├── profit-and-loss-row.ts │ │ │ └── tenant.ts │ │ └── utils.ts │ ├── frontend │ │ └── types.generated.ts │ └── types.generated.ts │ └── tsconfig.json ├── package.json ├── packages ├── admin-ui-components │ ├── .eslintrc.cjs │ ├── .npmrc │ ├── .prettierignore │ ├── .storybook │ │ ├── main.css │ │ ├── main.ts │ │ ├── manager.ts │ │ ├── preview.ts │ │ └── theme.ts │ ├── @types │ │ ├── auth.d.ts │ │ ├── custom-csv-export-overrides.d.ts │ │ ├── custom-fields.d.ts │ │ ├── custom-pages.d.ts │ │ └── vite-env.d.ts │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── 404-page │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── alert │ │ │ ├── alert.mdx │ │ │ ├── alert.stories.ts │ │ │ ├── alert.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── apollo.ts │ │ ├── assets │ │ │ ├── 16-arrow.tsx │ │ │ ├── 16-chevron-down.tsx │ │ │ ├── 16-database.tsx │ │ │ ├── 16-error.tsx │ │ │ ├── 16-filter.tsx │ │ │ ├── 16-info.tsx │ │ │ ├── 16-logout.tsx │ │ │ ├── 16-open-external.tsx │ │ │ ├── 16-search.tsx │ │ │ ├── 16-success.tsx │ │ │ ├── 16-table-light.tsx │ │ │ ├── 16-table.tsx │ │ │ ├── 16-warning.tsx │ │ │ ├── 24-database.tsx │ │ │ ├── 64-data-sources.tsx │ │ │ ├── checkmark.tsx │ │ │ ├── close-button.tsx │ │ │ ├── close-icon.tsx │ │ │ ├── editor-icons.tsx │ │ │ ├── graphweaver-logo-spinner.tsx │ │ │ ├── graphweaver-logo.tsx │ │ │ ├── index.ts │ │ │ ├── menu.tsx │ │ │ ├── request.tsx │ │ │ └── success-checkmark.tsx │ │ ├── badge │ │ │ ├── badge.mdx │ │ │ ├── badge.stories.tsx │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── button │ │ │ ├── button.mdx │ │ │ ├── button.stories.tsx │ │ │ ├── button.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── card │ │ │ ├── card.mdx │ │ │ ├── card.stories.tsx │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── checkbox │ │ │ ├── checkbox.mdx │ │ │ ├── checkbox.stories.tsx │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── combo-box │ │ │ ├── combo-box.mdx │ │ │ ├── combo-box.stories.tsx │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── config.ts │ │ ├── custom-page-config.ts │ │ ├── date-picker │ │ │ ├── component.tsx │ │ │ ├── date-picker.mdx │ │ │ ├── date-picker.stories.tsx │ │ │ ├── index.ts │ │ │ ├── styles.module.css │ │ │ ├── time-input.tsx │ │ │ └── utils.ts │ │ ├── default-error-fallback │ │ │ ├── component.tsx │ │ │ ├── default-error-fallback.mdx │ │ │ ├── default-error-fallback.stories.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── detail-panel-field-label │ │ │ ├── component.tsx │ │ │ ├── detail-panel-field-label.mdx │ │ │ ├── detail-panel-field-label.stories.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── detail-panel │ │ │ ├── component.tsx │ │ │ ├── detail-panel.mdx │ │ │ ├── detail-panel.stories.tsx │ │ │ ├── fields │ │ │ │ ├── boolean-field.tsx │ │ │ │ ├── date-field.tsx │ │ │ │ ├── enum-field.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── json-field.tsx │ │ │ │ ├── link-field.tsx │ │ │ │ ├── media-field │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.module.css │ │ │ │ ├── relationship-field.tsx │ │ │ │ ├── rich-text-field │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── menu-bar │ │ │ │ │ │ ├── button.tsx │ │ │ │ │ │ ├── component.tsx │ │ │ │ │ │ ├── header-options.tsx │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── link-button.tsx │ │ │ │ │ │ ├── list-options.tsx │ │ │ │ │ │ ├── styles.module.css │ │ │ │ │ │ └── utils.ts │ │ │ │ │ ├── styles.module.css │ │ │ │ │ └── utils.ts │ │ │ │ └── text-field.tsx │ │ │ ├── graphql.ts │ │ │ ├── index.ts │ │ │ ├── styles.module.css │ │ │ ├── use-data-transform.tsx │ │ │ └── util.ts │ │ ├── entity-list │ │ │ ├── columns.tsx │ │ │ ├── component.tsx │ │ │ ├── graphql.ts │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── error-view │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── export-modal │ │ │ ├── component.tsx │ │ │ ├── graphql.ts │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── filter-bar │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── filters │ │ │ ├── boolean-filter.tsx │ │ │ ├── date-range-filter.tsx │ │ │ ├── dropdown-text-filter.tsx │ │ │ ├── enum-filter.tsx │ │ │ ├── graphql.ts │ │ │ ├── index.ts │ │ │ ├── numeric-filter.tsx │ │ │ ├── numeric-range-filter │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── styles.module.css │ │ │ │ └── utils.ts │ │ │ ├── relationship-filter.tsx │ │ │ ├── text-filter.tsx │ │ │ └── utils.ts │ │ ├── form │ │ │ ├── component.tsx │ │ │ ├── form.mdx │ │ │ ├── form.stories.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── graphql-viewer │ │ │ ├── component.tsx │ │ │ ├── graphql-viewer.mdx │ │ │ ├── graphql-viewer.stories.tsx │ │ │ └── index.ts │ │ ├── header │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── hooks │ │ │ ├── hooks.mdx │ │ │ ├── hooks.stories.tsx │ │ │ ├── index.ts │ │ │ ├── use-auto-focus.mdx │ │ │ ├── use-auto-focus.stories.tsx │ │ │ ├── use-auto-focus.ts │ │ │ ├── use-debounce.mdx │ │ │ ├── use-debounce.stories.tsx │ │ │ └── use-debounce.ts │ │ ├── index.ts │ │ ├── input │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── input.mdx │ │ │ ├── input.stories.tsx │ │ │ └── styles.module.css │ │ ├── json-viewer │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── json-viewer.mdx │ │ │ └── json-viewer.stories.tsx │ │ ├── layouts │ │ │ ├── col │ │ │ │ ├── col.mdx │ │ │ │ ├── col.stories.tsx │ │ │ │ ├── component.tsx │ │ │ │ └── index.ts │ │ │ ├── default │ │ │ │ ├── component.tsx │ │ │ │ ├── default-layout.mdx │ │ │ │ ├── default-layout.stories.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ │ ├── grid │ │ │ │ ├── component.tsx │ │ │ │ ├── grid.mdx │ │ │ │ ├── grid.stories.tsx │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── layouts.mdx │ │ │ ├── layouts.stories.tsx │ │ │ ├── page │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── page.mdx │ │ │ │ └── page.stories.tsx │ │ │ ├── row │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── row.mdx │ │ │ │ └── row.stories.tsx │ │ │ └── styles.module.css │ │ ├── list-toolbar │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── list-toolbar.mdx │ │ │ └── list-toolbar.stories.tsx │ │ ├── loader │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── loader.mdx │ │ │ ├── loader.stories.tsx │ │ │ └── styles.module.css │ │ ├── missing-entity │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ │ ├── modal │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── modal.mdx │ │ │ ├── modal.stories.tsx │ │ │ └── styles.module.css │ │ ├── playground │ │ │ ├── component.tsx │ │ │ └── index.ts │ │ ├── popover │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── popover.mdx │ │ │ ├── popover.stories.tsx │ │ │ └── styles.module.css │ │ ├── popoverMenu │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── popoverMenu.mdx │ │ │ ├── popoverMenu.stories.tsx │ │ │ └── styles.module.css │ │ ├── require-schema │ │ │ ├── component.tsx │ │ │ └── index.ts │ │ ├── select │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── select.mdx │ │ │ ├── select.stories.tsx │ │ │ └── styles.module.css │ │ ├── selection-bar │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── selection-bar.mdx │ │ │ ├── selection-bar.stories.tsx │ │ │ └── styles.module.css │ │ ├── side-bar │ │ │ ├── component.tsx │ │ │ ├── contents │ │ │ │ ├── backend-row.tsx │ │ │ │ ├── dashboard-row.tsx │ │ │ │ ├── entity-row.tsx │ │ │ │ └── index.ts │ │ │ ├── graphql.ts │ │ │ ├── index.ts │ │ │ ├── side-bar.mdx │ │ │ ├── side-bar.stories.tsx │ │ │ └── styles.module.css │ │ ├── spacer │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── spacer.mdx │ │ │ └── spacer.stories.tsx │ │ ├── spinner │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── spinner.mdx │ │ │ ├── spinner.stories.tsx │ │ │ └── styles.module.css │ │ ├── star-field │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── large-star.tsx │ │ │ ├── small-star.tsx │ │ │ ├── star-field.mdx │ │ │ ├── star-field.stories.tsx │ │ │ └── styles.module.css │ │ ├── switch │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── styles.module.css │ │ │ ├── switch.mdx │ │ │ └── switch.stories.tsx │ │ ├── table │ │ │ ├── cells │ │ │ │ ├── boolean.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── json.tsx │ │ │ │ ├── media.tsx │ │ │ │ ├── nano-duration.tsx │ │ │ │ └── nano-timestamp.tsx │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── styles.module.css │ │ │ ├── table.mdx │ │ │ └── table.stories.tsx │ │ ├── title-bar │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── styles.module.css │ │ │ ├── title-bar.mdx │ │ │ └── title-bar.stories.tsx │ │ ├── toast │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── styles.module.css │ │ │ ├── toast.mdx │ │ │ └── toast.stories.tsx │ │ ├── toolbar │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── styles.module.css │ │ │ ├── toolbar.mdx │ │ │ └── toolbar.stories.tsx │ │ ├── trace-viewer │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ ├── span-view.tsx │ │ │ ├── styles.module.css │ │ │ ├── trace-viewer.mdx │ │ │ └── trace-viewer.stories.tsx │ │ ├── utils │ │ │ ├── data-loading.ts │ │ │ ├── export-csv.ts │ │ │ ├── graphql.ts │ │ │ ├── index.ts │ │ │ ├── route-for.ts │ │ │ ├── timestamp.ts │ │ │ ├── trace-to-tree.ts │ │ │ ├── use-schema.ts │ │ │ ├── use-selected-entity.ts │ │ │ └── utils.ts │ │ └── welcome-page │ │ │ ├── component.tsx │ │ │ ├── index.ts │ │ │ └── styles.module.css │ ├── tsconfig.json │ └── vite.config.ts ├── admin-ui │ ├── .gitignore │ ├── .prettierignore │ ├── @types │ │ ├── auth.d.ts │ │ ├── custom-csv-export-overrides.d.ts │ │ ├── custom-pages.d.ts │ │ ├── global.d.ts │ │ └── vite-env.d.ts │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── index.html │ │ ├── main.css │ │ ├── main.tsx │ │ ├── pages │ │ │ ├── analytics │ │ │ │ ├── component.tsx │ │ │ │ ├── graphql.ts │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ │ ├── index.ts │ │ │ ├── list │ │ │ │ ├── component.tsx │ │ │ │ ├── graphql.ts │ │ │ │ └── index.ts │ │ │ ├── playground │ │ │ │ ├── component.tsx │ │ │ │ └── index.ts │ │ │ └── root │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ ├── reset.css │ │ └── router.tsx │ └── tsconfig.json ├── apollo-client │ ├── .eslintrc.cjs │ ├── .npmrc │ ├── .prettierignore │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── auth-ui-components │ ├── .eslintrc.cjs │ ├── .npmrc │ ├── .prettierignore │ ├── @types │ │ └── vite-env.d.ts │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── assets │ │ │ ├── 16-logout.tsx │ │ │ └── index.ts │ │ ├── components │ │ │ ├── auth-zero │ │ │ │ ├── client.ts │ │ │ │ ├── index.ts │ │ │ │ ├── login │ │ │ │ │ ├── component.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── logout │ │ │ │ │ ├── component.tsx │ │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── logout │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ │ ├── magic-link │ │ │ │ ├── challenge │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── graphql.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.module.css │ │ │ │ ├── index.ts │ │ │ │ └── login │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── graphql.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.module.css │ │ │ ├── microsoft-entra │ │ │ │ ├── client.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── login │ │ │ │ │ ├── component.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── logout │ │ │ │ │ ├── component.tsx │ │ │ │ │ └── index.ts │ │ │ ├── okta │ │ │ │ ├── client.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── login │ │ │ │ │ ├── component.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── logout │ │ │ │ │ ├── component.tsx │ │ │ │ │ └── index.ts │ │ │ ├── one-time-password │ │ │ │ ├── challenge │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── graphql.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.module.css │ │ │ │ └── index.ts │ │ │ ├── passkey │ │ │ │ ├── challenge │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── graphql.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.module.css │ │ │ │ └── index.ts │ │ │ ├── password │ │ │ │ ├── challenge │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── graphql.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.module.css │ │ │ │ ├── forgotten-password │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── graphql.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.module.css │ │ │ │ ├── index.ts │ │ │ │ ├── login │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── graphql.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.module.css │ │ │ │ ├── password │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.module.css │ │ │ │ └── reset-password │ │ │ │ │ ├── component.tsx │ │ │ │ │ ├── graphql.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── styles.module.css │ │ │ ├── secret │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ │ ├── sign-out │ │ │ │ ├── component.tsx │ │ │ │ └── index.ts │ │ │ └── web3 │ │ │ │ ├── challenge │ │ │ │ ├── component.tsx │ │ │ │ ├── graphql.ts │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ │ │ └── index.ts │ │ ├── fields.tsx │ │ ├── globals.d.ts │ │ ├── index.ts │ │ ├── pages │ │ │ ├── auth │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ └── styles.module.css │ │ │ ├── challenge │ │ │ │ ├── component.tsx │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── routes.tsx │ │ ├── types.ts │ │ └── utils │ │ │ └── urls.ts │ └── tsconfig.json ├── auth │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── auth-utils.ts │ │ ├── authentication │ │ │ ├── apollo │ │ │ │ ├── index.ts │ │ │ │ └── plugin.ts │ │ │ ├── entities │ │ │ │ ├── api-key.ts │ │ │ │ ├── authentication.ts │ │ │ │ ├── credential.ts │ │ │ │ ├── index.ts │ │ │ │ └── token.ts │ │ │ ├── index.ts │ │ │ ├── methods │ │ │ │ ├── api-key.ts │ │ │ │ ├── auth-zero.ts │ │ │ │ ├── base-auth-method.ts │ │ │ │ ├── forgotten-password.ts │ │ │ │ ├── index.ts │ │ │ │ ├── magic-link.ts │ │ │ │ ├── microsoft-entra.ts │ │ │ │ ├── okta.ts │ │ │ │ ├── one-time-password.ts │ │ │ │ ├── passkey.ts │ │ │ │ ├── password.ts │ │ │ │ ├── utils.ts │ │ │ │ └── web3.ts │ │ │ └── token │ │ │ │ ├── auth-token.ts │ │ │ │ ├── base-auth-token-provider.ts │ │ │ │ └── index.ts │ │ ├── authorization-context.ts │ │ ├── decorators │ │ │ ├── apply-access-control-list.ts │ │ │ ├── apply-multi-factor-authentication.ts │ │ │ ├── hooks │ │ │ │ └── acl.ts │ │ │ └── index.ts │ │ ├── errors.ts │ │ ├── helper-functions.test.ts │ │ ├── helper-functions.ts │ │ ├── implicit-authorization.ts │ │ ├── index.ts │ │ ├── types.ts │ │ ├── user-context.ts │ │ ├── user-profile.ts │ │ └── utils │ │ │ ├── argon2id.test.ts │ │ │ ├── argon2id.ts │ │ │ ├── get-rules-for-roles.test.ts │ │ │ └── get-rules-for-roles.ts │ ├── tsconfig.json │ └── vite.config.ts ├── aws-cognito │ ├── .prettierignore │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── entities │ │ │ ├── backend-entity.ts │ │ │ ├── graphql-entity.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── provider │ │ │ ├── base-provider.ts │ │ │ ├── index.ts │ │ │ └── user-provider.ts │ │ └── util.ts │ └── tsconfig.json ├── builder │ ├── .gitignore │ ├── .prettierignore │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── auth │ │ │ ├── api-key.ts │ │ │ ├── config.ts │ │ │ ├── env.test.ts │ │ │ ├── env.ts │ │ │ ├── index.ts │ │ │ ├── password.ts │ │ │ └── utils.ts │ │ ├── build │ │ │ ├── backend.ts │ │ │ ├── frontend.ts │ │ │ └── index.ts │ │ ├── bundle │ │ │ ├── analyse.ts │ │ │ └── index.ts │ │ ├── codegen │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── introspection │ │ │ └── index.ts │ │ ├── start │ │ │ ├── backend.ts │ │ │ ├── frontend.ts │ │ │ └── index.ts │ │ ├── util.ts │ │ └── vite-config.ts │ ├── tsconfig.json │ └── vite.config.ts ├── cdk │ ├── .eslintrc.js │ ├── .gitignore │ ├── README.md │ ├── build.js │ ├── cdk.json │ ├── package.json │ ├── src │ │ ├── app │ │ │ ├── database.ts │ │ │ ├── ecs.ts │ │ │ ├── lambda.ts │ │ │ ├── types.ts │ │ │ └── website.ts │ │ ├── docker │ │ │ └── Dockerfile │ │ ├── examples │ │ │ ├── ecs.test.ts │ │ │ ├── ecs.ts │ │ │ ├── lambda.test.ts │ │ │ └── lambda.ts │ │ └── index.ts │ └── tsconfig.json ├── cli │ ├── .gitignore │ ├── .prettierignore │ ├── README.md │ ├── bin │ │ ├── gw-bin.js │ │ ├── gw-print-schema.js │ │ └── gw-types.js │ ├── build.js │ ├── package.json │ ├── pnpm-lock.yaml │ ├── src │ │ ├── auth │ │ │ └── index.ts │ │ ├── database.ts │ │ ├── import │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── init │ │ │ ├── backend.ts │ │ │ ├── constants.ts │ │ │ ├── index.ts │ │ │ └── template.ts │ │ └── tasks.ts │ ├── test-init.js │ └── tsconfig.json ├── config │ ├── .gitignore │ ├── .prettierignore │ ├── README.md │ ├── build.js │ ├── package.json │ ├── pnpm-lock.yaml │ ├── src │ │ ├── config.ts │ │ └── index.ts │ └── tsconfig.json ├── core │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── base-data-provider.ts │ │ ├── base-entities.ts │ │ ├── base-loader.ts │ │ ├── decorators │ │ │ ├── entity.ts │ │ │ ├── field.ts │ │ │ ├── hook.ts │ │ │ ├── index.ts │ │ │ ├── input-type.ts │ │ │ ├── provider.ts │ │ │ └── relationship-field.ts │ │ ├── default-from-backend-entity.ts │ │ ├── federation │ │ │ ├── directives.ts │ │ │ ├── entities.ts │ │ │ ├── enums.ts │ │ │ ├── index.ts │ │ │ ├── scalars.ts │ │ │ ├── service.ts │ │ │ └── utils.ts │ │ ├── field-resolver.ts │ │ ├── hook-manager.ts │ │ ├── index.ts │ │ ├── metadata-service │ │ │ ├── entity-attribute.ts │ │ │ ├── entity.ts │ │ │ ├── enum-value.ts │ │ │ ├── enum.ts │ │ │ ├── field-attribute.ts │ │ │ ├── field-extensions.ts │ │ │ ├── field-format.ts │ │ │ ├── field.ts │ │ │ ├── filter.ts │ │ │ ├── index.ts │ │ │ ├── metadata.ts │ │ │ └── resolver.ts │ │ ├── metadata.test.ts │ │ ├── metadata.ts │ │ ├── open-telemetry │ │ │ ├── entity.ts │ │ │ ├── exporter.ts │ │ │ ├── index.ts │ │ │ └── tracing.ts │ │ ├── operations.ts │ │ ├── query-manager.ts │ │ ├── request-context.ts │ │ ├── resolvers.ts │ │ ├── schema-builder.ts │ │ ├── types.ts │ │ └── utils │ │ │ ├── apply-default-values.ts │ │ │ ├── batched-writes.ts │ │ │ ├── common.ts │ │ │ ├── create-or-update-entities.ts │ │ │ ├── has-id.ts │ │ │ ├── index.ts │ │ │ ├── plural.ts │ │ │ ├── resolver.utils.ts │ │ │ └── with-transaction.ts │ └── tsconfig.json ├── end-to-end │ ├── .env.rest.example │ ├── .env.sqlite │ ├── .gitignore │ ├── README.md │ ├── databases │ │ ├── database.sqlite │ │ ├── mysql.sql │ │ └── postgres.sql │ ├── jest.config.js │ ├── jest.setup.js │ ├── package.json │ ├── playwright.config.ts │ ├── scripts │ │ ├── import-auth.ts │ │ ├── import-auth0.ts │ │ ├── import-mysql.sh │ │ ├── import-postgres.sh │ │ ├── import-rest.ts │ │ ├── import-sqlite.ts │ │ ├── import-storage-provider.ts │ │ ├── seed-postgres.js │ │ └── unpack.ts │ ├── src │ │ ├── __tests__ │ │ │ ├── api │ │ │ │ ├── auth │ │ │ │ │ ├── acl │ │ │ │ │ │ ├── EXOGW-416.test.ts │ │ │ │ │ │ ├── access-control-list.test.ts │ │ │ │ │ │ ├── admin-ui-metadata.test.ts │ │ │ │ │ │ ├── basic-before-hook.test.ts │ │ │ │ │ │ ├── column-level-security.test.ts │ │ │ │ │ │ ├── create-or-update.test.ts │ │ │ │ │ │ ├── fragments.test.ts │ │ │ │ │ │ ├── implicit-deny.test.ts │ │ │ │ │ │ ├── multiple-roles.test.ts │ │ │ │ │ │ ├── nested-before-hook.test.ts │ │ │ │ │ │ ├── nested-filters.test.ts │ │ │ │ │ │ ├── top-level-filters.test.ts │ │ │ │ │ │ └── without-transaction-before-hook.test.ts │ │ │ │ │ ├── api-key │ │ │ │ │ │ ├── api-key.test.ts │ │ │ │ │ │ └── roles.test.ts │ │ │ │ │ ├── magic-link │ │ │ │ │ │ ├── challenge.test.ts │ │ │ │ │ │ └── login.test.ts │ │ │ │ │ ├── one-time-password │ │ │ │ │ │ └── challenge.test.ts │ │ │ │ │ ├── passkey │ │ │ │ │ │ └── generate-register-options.test.ts │ │ │ │ │ ├── password │ │ │ │ │ │ ├── challenge.test.ts │ │ │ │ │ │ ├── login.test.ts │ │ │ │ │ │ ├── redirect.test.ts │ │ │ │ │ │ ├── register.test.ts │ │ │ │ │ │ └── reset.test.ts │ │ │ │ │ ├── security │ │ │ │ │ │ ├── invalid-token.test.ts │ │ │ │ │ │ └── max-depth.test.ts │ │ │ │ │ └── web3 │ │ │ │ │ │ └── challenge.test.ts │ │ │ │ ├── metadata │ │ │ │ │ ├── aggregation-not-supported-in-provider.test.ts │ │ │ │ │ ├── before-read-hook-via-entity-decorator.test.ts │ │ │ │ │ ├── before-read-hook-via-hook-decorator.test.ts │ │ │ │ │ ├── before-read-hook-via-method-decorator.test.ts │ │ │ │ │ ├── custom-queries.test.ts │ │ │ │ │ ├── exclude-from-federation.test.ts │ │ │ │ │ ├── missing-entity-decorator-validation.test.ts │ │ │ │ │ ├── multiple-prefix-for-plural.test.ts │ │ │ │ │ ├── override-plural.test.ts │ │ │ │ │ ├── plural.test.ts │ │ │ │ │ ├── providerless-entity-foreign-key-field.test.ts │ │ │ │ │ └── reserved-entity-names.ts │ │ │ │ ├── mysql │ │ │ │ │ └── query │ │ │ │ │ │ ├── basic-filter.test.ts │ │ │ │ │ │ ├── basic-list.test.ts │ │ │ │ │ │ └── ilike-filter.test.ts │ │ │ │ ├── postgres │ │ │ │ │ ├── issues │ │ │ │ │ │ ├── exogw384.test.ts │ │ │ │ │ │ └── nested.test.ts │ │ │ │ │ └── query │ │ │ │ │ │ ├── basic-filter.test.ts │ │ │ │ │ │ ├── basic-list.test.ts │ │ │ │ │ │ ├── enum-filter.test.ts │ │ │ │ │ │ └── null-filter.test.ts │ │ │ │ ├── scalars │ │ │ │ │ └── graphql-json.test.ts │ │ │ │ ├── sqlite │ │ │ │ │ ├── issues │ │ │ │ │ │ ├── exogw384-nested.test.ts │ │ │ │ │ │ ├── gh1388.test.ts │ │ │ │ │ │ ├── gh146.test.ts │ │ │ │ │ │ └── gh151.test.ts │ │ │ │ │ ├── mutation │ │ │ │ │ │ ├── basic-create.test.ts │ │ │ │ │ │ └── nested-create.test.ts │ │ │ │ │ └── query │ │ │ │ │ │ ├── adminUISettings.test.ts │ │ │ │ │ │ ├── basic-filter.test.ts │ │ │ │ │ │ ├── basic-list.test.ts │ │ │ │ │ │ ├── export-page-size-decorator.test.ts │ │ │ │ │ │ ├── field-aggregation.test.ts │ │ │ │ │ │ ├── field-isArray.test.ts │ │ │ │ │ │ ├── ilike-filter.test.ts │ │ │ │ │ │ ├── read-only-entity.test.ts │ │ │ │ │ │ ├── read-only-field.test.ts │ │ │ │ │ │ └── root-aggregation.test.ts │ │ │ │ └── storage-provider │ │ │ │ │ ├── fixtures │ │ │ │ │ ├── pickle.png │ │ │ │ │ └── tomato-chair.png │ │ │ │ │ └── issues │ │ │ │ │ └── gh1458.test.ts │ │ │ ├── fuzzer │ │ │ │ ├── tests │ │ │ │ │ ├── authn.test.ts │ │ │ │ │ └── queries.test.ts │ │ │ │ └── utils │ │ │ │ │ ├── fuzzer.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── static.ts │ │ │ └── ui │ │ │ │ ├── auth │ │ │ │ ├── README.md │ │ │ │ ├── api-key.test.ts │ │ │ │ ├── column-level-security.test.ts │ │ │ │ ├── create-user.test.ts │ │ │ │ ├── delete-tag.test.ts │ │ │ │ ├── login.test.ts │ │ │ │ ├── logout.test.ts │ │ │ │ ├── password-strength.test.ts │ │ │ │ ├── trace.test.ts │ │ │ │ ├── update-user.test.ts │ │ │ │ └── virtual-entities.test.ts │ │ │ │ ├── postgres │ │ │ │ └── enum-editor.test.ts │ │ │ │ ├── rest │ │ │ │ ├── basic-functionality.test.ts │ │ │ │ └── playground.test.ts │ │ │ │ ├── sqlite │ │ │ │ ├── components │ │ │ │ │ ├── 404-pages.test.ts │ │ │ │ │ ├── combobox.test.ts │ │ │ │ │ ├── date-picker.test.ts │ │ │ │ │ ├── filters.test.ts │ │ │ │ │ ├── list-page.test.ts │ │ │ │ │ └── sidebar.test.ts │ │ │ │ └── issues │ │ │ │ │ ├── gh192.test.ts │ │ │ │ │ ├── gh218.test.ts │ │ │ │ │ ├── gh249.test.ts │ │ │ │ │ └── gh270.test.ts │ │ │ │ └── storage-provider │ │ │ │ ├── client-provided-id.test.ts │ │ │ │ ├── fixtures │ │ │ │ ├── pickle.png │ │ │ │ └── tomato-chair.png │ │ │ │ └── media.test.ts │ │ ├── config.ts │ │ └── utils.ts │ └── tsconfig.json ├── load-testing │ ├── .gitignore │ ├── README.md │ ├── bin │ │ └── k6 │ ├── package.json │ ├── src │ │ ├── config.ts │ │ ├── create-one.ts │ │ └── metadata.ts │ └── tsconfig.json ├── logger │ ├── .eslintrc.js │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── logger.ts │ └── tsconfig.json ├── mikro-orm-sqlite-wasm │ ├── build.js │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── mikroorm │ ├── .eslintrc.js │ ├── README.md │ ├── build.js │ ├── package.json │ ├── scripts │ │ ├── check-mikro-overrides-match-installed-versions.ts │ │ └── test-introspection.ts │ ├── src │ │ ├── config.ts │ │ ├── database.ts │ │ ├── decorators │ │ │ ├── external-id-field.ts │ │ │ └── index.ts │ │ ├── entities │ │ │ ├── audit-change.ts │ │ │ ├── audit-related-entity-change.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── introspection │ │ │ ├── files │ │ │ │ ├── base-file.ts │ │ │ │ ├── data-entity-file.ts │ │ │ │ ├── data-entity-index-file.ts │ │ │ │ ├── data-source-index-file.ts │ │ │ │ ├── database-file.ts │ │ │ │ ├── index.ts │ │ │ │ ├── schema-entity-file.ts │ │ │ │ └── schema-index-file.ts │ │ │ ├── generate.ts │ │ │ ├── index.ts │ │ │ └── utils.ts │ │ ├── plugins │ │ │ ├── connect-to-database.ts │ │ │ └── index.ts │ │ ├── provider │ │ │ ├── assign.ts │ │ │ ├── index.ts │ │ │ ├── provider.test.ts │ │ │ └── provider.ts │ │ ├── types │ │ │ ├── date-type.ts │ │ │ ├── decimal-type.ts │ │ │ ├── index.ts │ │ │ └── time-type.ts │ │ └── utils │ │ │ ├── authentication-context.ts │ │ │ ├── change-tracker.ts │ │ │ ├── errors.ts │ │ │ ├── index.ts │ │ │ ├── tracked-entity.ts │ │ │ └── untracked-property.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── rest-legacy │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── decorators │ │ │ ├── external-id-field.ts │ │ │ ├── field.ts │ │ │ ├── index.ts │ │ │ ├── many-to-many.ts │ │ │ ├── many-to-one.ts │ │ │ └── one-to-many.ts │ │ ├── entities │ │ │ ├── base-entity.ts │ │ │ └── index.ts │ │ ├── entity-manager.ts │ │ ├── index.ts │ │ ├── provider │ │ │ ├── index.ts │ │ │ ├── loader.ts │ │ │ └── provider.ts │ │ ├── serializers │ │ │ ├── date-serializer.ts │ │ │ └── index.ts │ │ └── utils │ │ │ ├── index.ts │ │ │ └── memory-filter.ts │ └── tsconfig.json ├── rest │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── provider.ts │ │ ├── utils.test.ts │ │ └── utils.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── scalars │ ├── .eslintrc.js │ ├── .npmrc │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── date.ts │ │ ├── decimal.ts │ │ ├── index.ts │ │ ├── iso-string.ts │ │ ├── nano-duration.ts │ │ ├── nano-timestamp.ts │ │ └── time.ts │ └── tsconfig.json ├── server │ ├── .npmrc │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── apollo-plugins │ │ │ ├── apollo-plugin-manager.ts │ │ │ ├── cors.ts │ │ │ ├── graphql-deduplicator.ts │ │ │ ├── index.ts │ │ │ ├── log-errors.ts │ │ │ ├── log-requests.test.ts │ │ │ ├── log-requests.ts │ │ │ └── utils.ts │ │ ├── config.ts │ │ ├── index.ts │ │ ├── integrations │ │ │ ├── fastify.ts │ │ │ ├── index.ts │ │ │ ├── lambda.ts │ │ │ └── utils.ts │ │ ├── plugin-manager.ts │ │ ├── server.ts │ │ └── trace.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── storage-provider │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── decorators │ │ │ └── media-field.ts │ │ ├── index.ts │ │ └── storageProvider.ts │ └── tsconfig.json ├── vite-plugin-graphweaver │ ├── .eslintrc.js │ ├── .npmrc │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── loaders │ │ │ ├── auth.ts │ │ │ ├── csv-export-overrides.ts │ │ │ ├── custom-fields.ts │ │ │ ├── custom-pages.ts │ │ │ ├── index.ts │ │ │ └── util.ts │ └── tsconfig.json └── xero │ ├── README.md │ ├── build.js │ ├── package.json │ ├── src │ ├── apollo-plugins │ │ ├── index.ts │ │ └── xero-auth-apollo-plugin.ts │ ├── index.ts │ └── provider │ │ ├── index.ts │ │ └── provider.ts │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── tsconfig.json └── turbo.json /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/gitleaks/gitleaks 3 | rev: v8.18.2 4 | hooks: 5 | - id: gitleaks 6 | -------------------------------------------------------------------------------- /.sonarcloud.properties: -------------------------------------------------------------------------------- 1 | # *.generated.ts files are generated from GraphQL types. 2 | # database.sql files are from https://github.com/lerocha/chinook-database and are not relevant to our code directly. 3 | sonar.exclusions=**/*.generated.ts,**/database.sql 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "./src/node_modules/typescript/lib" 3 | } -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Currently being supported with security updates. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 1.x.x | :white_check_mark: | 10 | | 0.x.x | :white_check_mark: | 11 | 12 | ## Reporting a Vulnerability 13 | 14 | Please do not create GitHub issues to report security vulnerabilities. 15 | 16 | Instead, report them via hello@graphweaver.com. 17 | -------------------------------------------------------------------------------- /src/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true 2 | -------------------------------------------------------------------------------- /src/.nvmrc: -------------------------------------------------------------------------------- 1 | v22 -------------------------------------------------------------------------------- /src/.prettierignore: -------------------------------------------------------------------------------- 1 | @types 2 | **/node_modules/** 3 | **/lib/** 4 | **/build/** 5 | **/dist/** 6 | **/.graphweaver/** 7 | .eslintrc.js 8 | *.generated.ts 9 | pnpm-lock.yaml 10 | pnpm-workspace.yaml 11 | examples/**/src/frontend/types.generated.ts 12 | -------------------------------------------------------------------------------- /src/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "printWidth": 100, 4 | "semi": true, 5 | "singleQuote": true, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /src/examples/auth-zero/.env.example: -------------------------------------------------------------------------------- 1 | AUTH_BASE_URI="http://localhost:9000" 2 | AUTH_WHITELIST_DOMAINS="localhost" 3 | AUTH_JWKS_URI="https://YOUR_AUTH0_DOMAIN/.well-known/jwks.json" 4 | AUTH_JWT_ALGORITHM="RS256" 5 | 6 | VITE_AUTH_ZERO_DOMAIN='YOUR_AUTH0_DOMAIN' 7 | VITE_AUTH_CLIENT_ID='YOUR_AUTH0_CLIENT_ID' -------------------------------------------------------------------------------- /src/examples/auth-zero/databases/database.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/examples/auth-zero/databases/database.sqlite -------------------------------------------------------------------------------- /src/examples/auth-zero/graphweaver-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | adminUI: { 3 | auth: { 4 | primaryMethods: ['AUTH_ZERO'], 5 | }, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/admin-ui/custom-pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { WelcomePage } from './welcome-page'; 2 | 3 | export const customPages = { 4 | defaultRoute: '/welcome', 5 | routes: () => [ 6 | { 7 | path: '/welcome', 8 | element: , 9 | }, 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/admin-ui/custom-pages/welcome-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/admin-ui/custom-pages/welcome-page/styles.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | font-size: 2.2rem; 3 | font-weight: bold; 4 | line-height: 3rem; 5 | } 6 | 7 | .list { 8 | list-style: disc; 9 | margin-left: 2rem; 10 | } 11 | 12 | .button { 13 | width: 200px; 14 | justify-content: space-between; 15 | margin-left: auto; 16 | } 17 | 18 | .arrow { 19 | height: 8px; 20 | } 21 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/backend/auth/auth-zero.ts: -------------------------------------------------------------------------------- 1 | import { UserProfile, AuthZero, setAddUserToContext } from '@exogee/graphweaver-auth'; 2 | 3 | export const authZero = new AuthZero(); 4 | 5 | export const addUserToContext = async (userId: string) => { 6 | return new UserProfile({ 7 | id: userId, 8 | roles: ['everyone'], 9 | }); 10 | }; 11 | // This function is called when a user logs in 12 | setAddUserToContext(addUserToContext); 13 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/backend/auth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auth-zero'; 2 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/backend/database.ts: -------------------------------------------------------------------------------- 1 | import { SqliteDriver } from 'mikro-orm-sqlite-wasm'; 2 | import { entities } from './entities'; 3 | 4 | export const connection = { 5 | connectionManagerId: 'sqlite', 6 | mikroOrmConfig: { 7 | entities: entities, 8 | driver: SqliteDriver, 9 | dbName: 'databases/database.sqlite', 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/backend/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sqlite'; 2 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/backend/entities/sqlite/artist.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Album } from './album'; 3 | 4 | @Entity({ tableName: 'Artist' }) 5 | export class Artist { 6 | @PrimaryKey({ fieldName: 'ArtistId', type: 'number' }) 7 | artistId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Album, mappedBy: 'artist' }) 13 | albums = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/backend/entities/sqlite/genre.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'Genre' }) 5 | export class Genre { 6 | @PrimaryKey({ fieldName: 'GenreId', type: 'number' }) 7 | genreId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Track, mappedBy: 'genre' }) 13 | tracks = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/backend/entities/sqlite/media-type.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'MediaType' }) 5 | export class MediaType { 6 | @PrimaryKey({ fieldName: 'MediaTypeId', type: 'number' }) 7 | mediaTypeId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Track, mappedBy: 'mediaType' }) 13 | tracks = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/backend/entities/sqlite/playlist.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, ManyToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'Playlist' }) 5 | export class Playlist { 6 | @PrimaryKey({ fieldName: 'PlaylistId', type: 'number' }) 7 | playlistId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @ManyToMany({ 13 | entity: () => Track, 14 | pivotTable: 'PlaylistTrack', 15 | joinColumn: 'PlaylistId', 16 | inverseJoinColumn: 'TrackId', 17 | }) 18 | tracks = new Collection(this); 19 | } 20 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/backend/index.ts: -------------------------------------------------------------------------------- 1 | import Graphweaver from '@exogee/graphweaver-server'; 2 | 3 | import './auth'; 4 | import './schema'; 5 | 6 | export const graphweaver = new Graphweaver(); 7 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/backend/schema/index.ts: -------------------------------------------------------------------------------- 1 | import './album'; 2 | import './artist'; 3 | import './customer'; 4 | import './employee'; 5 | import './genre'; 6 | import './invoice'; 7 | import './invoice-line'; 8 | import './media-type'; 9 | import './playlist'; 10 | import './track'; 11 | -------------------------------------------------------------------------------- /src/examples/auth-zero/src/css-modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.css' { 2 | const content: Record; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /src/examples/aws-cognito/.env.example: -------------------------------------------------------------------------------- 1 | COGNITO_ENDPOINT=http://localhost:9229 2 | COGNITO_USER_POOL_ID=MyUserPool 3 | AWS_REGION=us-east-1 4 | -------------------------------------------------------------------------------- /src/examples/aws-cognito/.gitignore: -------------------------------------------------------------------------------- 1 | # Working build files 2 | .esbuild 3 | .graphweaver 4 | -------------------------------------------------------------------------------- /src/examples/aws-cognito/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/examples/aws-cognito/src/admin-ui/custom-pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { WelcomePage } from './welcome-page'; 2 | 3 | export const customPages = { 4 | defaultRoute: '/welcome', 5 | routes: () => [ 6 | { 7 | path: '/welcome', 8 | element: , 9 | }, 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /src/examples/aws-cognito/src/admin-ui/custom-pages/welcome-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/aws-cognito/src/admin-ui/custom-pages/welcome-page/styles.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | font-size: 2.2rem; 3 | font-weight: bold; 4 | line-height: 3rem; 5 | } 6 | 7 | .button { 8 | width: 200px; 9 | justify-content: space-between; 10 | margin-left: auto; 11 | } 12 | 13 | .arrow { 14 | height: 8px; 15 | } 16 | -------------------------------------------------------------------------------- /src/examples/aws-cognito/src/backend/index.ts: -------------------------------------------------------------------------------- 1 | import Graphweaver from '@exogee/graphweaver-server'; 2 | import { createAwsCognitoUserProvider } from '@exogee/graphweaver-aws'; 3 | 4 | export const cognitoUser = createAwsCognitoUserProvider({ 5 | userPoolId: process.env.COGNITO_USER_POOL_ID, 6 | region: process.env.AWS_REGION, 7 | endpoint: process.env.COGNITO_ENDPOINT, 8 | }); 9 | 10 | export const graphweaver = new Graphweaver(); 11 | -------------------------------------------------------------------------------- /src/examples/aws-cognito/src/css-modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.css' { 2 | const content: Record; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /src/examples/databases/.env.example: -------------------------------------------------------------------------------- 1 | # Note: If your local Postgres and MySQL instances are configured to allow passwordless access, you may not even need 2 | # a .env file at all. If, however, you'd like to change the connection details, you can copy this file to .env 3 | # and modify to your heart's content. 4 | 5 | # Postgres 6 | POSTGRES_DB_NAME=todo_app 7 | POSTGRES_DB_USER=postgres 8 | POSTGRES_DB_PASSWORD=postgres 9 | POSTGRES_DB_PORT=5432 10 | 11 | # MySQL 12 | MYSQL_DB_NAME=todo_app 13 | MYSQL_DB_USER=root 14 | MYSQL_DB_PASSWORD=root 15 | MYSQL_DB_PORT=3306 16 | -------------------------------------------------------------------------------- /src/examples/databases/.gitignore: -------------------------------------------------------------------------------- 1 | # Working build files 2 | .esbuild 3 | .graphweaver 4 | -------------------------------------------------------------------------------- /src/examples/databases/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/examples/databases/src/admin-ui/custom-pages/index.tsx: -------------------------------------------------------------------------------- 1 | import type { CustomPageConfiguration } from '@exogee/graphweaver-admin-ui-components'; 2 | import { WelcomePage } from './welcome-page'; 3 | 4 | export const customPages: CustomPageConfiguration = { 5 | defaultRoute: '/welcome', 6 | routes: () => [ 7 | { 8 | path: '/welcome', 9 | element: , 10 | }, 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /src/examples/databases/src/admin-ui/custom-pages/welcome-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/databases/src/admin-ui/custom-pages/welcome-page/styles.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | font-size: 2.2rem; 3 | font-weight: bold; 4 | line-height: 3rem; 5 | } 6 | 7 | .list { 8 | list-style: disc; 9 | margin-left: 2rem; 10 | } 11 | 12 | .button { 13 | width: 200px; 14 | justify-content: space-between; 15 | margin-left: auto; 16 | } 17 | 18 | .arrow { 19 | height: 8px; 20 | } 21 | -------------------------------------------------------------------------------- /src/examples/databases/src/backend/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './postgresql'; 2 | export * from './mysql'; 3 | -------------------------------------------------------------------------------- /src/examples/databases/src/backend/entities/mysql/index.ts: -------------------------------------------------------------------------------- 1 | export * from './task'; 2 | -------------------------------------------------------------------------------- /src/examples/databases/src/backend/entities/postgresql/index.ts: -------------------------------------------------------------------------------- 1 | export * from './user'; 2 | -------------------------------------------------------------------------------- /src/examples/databases/src/backend/index.ts: -------------------------------------------------------------------------------- 1 | import Graphweaver from '@exogee/graphweaver-server'; 2 | import 'json-bigint-patch'; 3 | 4 | import './schema'; 5 | 6 | export const graphweaver = new Graphweaver(); 7 | -------------------------------------------------------------------------------- /src/examples/databases/src/backend/schema/index.ts: -------------------------------------------------------------------------------- 1 | import './user'; 2 | import './task'; 3 | -------------------------------------------------------------------------------- /src/examples/databases/src/css-modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.css' { 2 | const content: Record; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /src/examples/federation/.gitignore: -------------------------------------------------------------------------------- 1 | # Working build files 2 | .esbuild 3 | .graphweaver 4 | 5 | # Subgraph Test Files 6 | supergraph* 7 | results.md 8 | package-lock.json 9 | integration/index.js 10 | integration/schema.graphql -------------------------------------------------------------------------------- /src/examples/federation/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/examples/federation/README.md: -------------------------------------------------------------------------------- 1 | # Graphweaver Federation 2 | 3 | This example is used by our end-to-end tests to confirm Apollo federation compatibility. 4 | 5 | To run the integration locally, use: 6 | 7 | `pnpm start` 8 | 9 | You can also run the tests using: 10 | 11 | `pnpm test:integration` 12 | 13 | To run the test suite, you will need to make sure that you have docker installed locally. 14 | -------------------------------------------------------------------------------- /src/examples/federation/integration/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18-alpine 2 | WORKDIR /app 3 | COPY index.js index.js 4 | ENV GRAPHWEAVER_API_PORT=4001 5 | EXPOSE 4001 6 | CMD node index.js -------------------------------------------------------------------------------- /src/examples/federation/integration/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | products: 3 | build: . 4 | ports: 5 | - 4001:4001 6 | -------------------------------------------------------------------------------- /src/examples/federation/integration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "federation-integration-test", 3 | "scripts": { 4 | "build": "docker build --platform linux/amd64 -t gw-integration:test .", 5 | "start": "docker run --platform linux/amd64 -p 4001:4001 gw-integration:test", 6 | "test:integration": "node integration-test.js" 7 | }, 8 | "dependencies": { 9 | "@apollo/federation-subgraph-compatibility": "2.2.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/examples/federation/src/backend/schema/case-study.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field, ID } from '@exogee/graphweaver'; 2 | 3 | // type CaseStudy { 4 | // caseNumber: ID! 5 | // description: String 6 | // } 7 | 8 | @Entity('CaseStudy', { 9 | apiOptions: { excludeFromBuiltInOperations: true }, 10 | }) 11 | export class CaseStudy { 12 | @Field(() => ID, { primaryKeyField: true }) 13 | caseNumber!: string; 14 | 15 | @Field(() => String, { nullable: true }) 16 | description?: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/examples/federation/src/backend/schema/hidden-entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field, ID } from '@exogee/graphweaver'; 2 | 3 | @Entity('HiddenEntity', { 4 | apiOptions: { excludeFromBuiltInOperations: true, excludeFromFederation: true }, 5 | }) 6 | export class HiddenEntity { 7 | @Field(() => ID, { primaryKeyField: true }) 8 | id!: string; 9 | 10 | @Field(() => String, { nullable: true }) 11 | name?: string; 12 | } 13 | -------------------------------------------------------------------------------- /src/examples/federation/src/backend/schema/index.ts: -------------------------------------------------------------------------------- 1 | import './case-study'; 2 | import './deprecated-product'; 3 | import './hidden-entity'; 4 | import './inventory'; 5 | import './non-resolvable-entity'; 6 | import './product-dimension'; 7 | import './product-research'; 8 | import './product-variation'; 9 | import './product'; 10 | import './user'; 11 | -------------------------------------------------------------------------------- /src/examples/federation/src/backend/schema/non-resolvable-entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field, ID } from '@exogee/graphweaver'; 2 | 3 | @Entity('NonResolvableEntity', { 4 | apiOptions: { excludeFromBuiltInOperations: true, resolvableViaFederation: false }, 5 | }) 6 | export class NonResolvableEntity { 7 | @Field(() => ID, { primaryKeyField: true }) 8 | id!: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/examples/federation/src/backend/schema/product-variation.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field, ID } from '@exogee/graphweaver'; 2 | 3 | // type ProductVariation { 4 | // id: ID! 5 | // } 6 | 7 | @Entity('ProductVariation', { 8 | apiOptions: { excludeFromBuiltInOperations: true }, 9 | }) 10 | export class ProductVariation { 11 | @Field(() => ID, { primaryKeyField: true }) 12 | id!: string; 13 | } 14 | -------------------------------------------------------------------------------- /src/examples/federation/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "rootDir": "./src", 5 | "noUnusedLocals": false, 6 | "experimentalDecorators": true, 7 | "emitDecoratorMetadata": true, 8 | "target": "es2019", 9 | "module": "CommonJS", 10 | "allowSyntheticDefaultImports": true, 11 | "esModuleInterop": true, 12 | "skipLibCheck": true 13 | }, 14 | "exclude": ["**/node_modules/**", "**/lib/**"], 15 | "include": ["./src"], 16 | "references": [ 17 | { "path": "../../packages/admin-ui-components" }, 18 | { "path": "../../packages/builder" }, 19 | { "path": "../../packages/core" }, 20 | { "path": "../../packages/server" } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/databases/database.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/examples/microsoft-entra/databases/database.sqlite -------------------------------------------------------------------------------- /src/examples/microsoft-entra/graphweaver-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | adminUI: { 3 | auth: { 4 | primaryMethods: ['MICROSOFT_ENTRA'], 5 | }, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/admin-ui/custom-pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { WelcomePage } from './welcome-page'; 2 | 3 | export const customPages = { 4 | defaultRoute: '/welcome', 5 | routes: () => [ 6 | { 7 | path: '/welcome', 8 | element: , 9 | }, 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/admin-ui/custom-pages/welcome-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/admin-ui/custom-pages/welcome-page/styles.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | font-size: 2.2rem; 3 | font-weight: bold; 4 | line-height: 3rem; 5 | } 6 | 7 | .list { 8 | list-style: disc; 9 | margin-left: 2rem; 10 | } 11 | 12 | .button { 13 | width: 200px; 14 | justify-content: space-between; 15 | margin-left: auto; 16 | } 17 | 18 | .arrow { 19 | height: 8px; 20 | } 21 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/backend/auth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './microsoft-entra'; 2 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/backend/auth/microsoft-entra.ts: -------------------------------------------------------------------------------- 1 | import { UserProfile, MicrosoftEntra, setAddUserToContext } from '@exogee/graphweaver-auth'; 2 | 3 | export const microsoftEntra = new MicrosoftEntra(); 4 | 5 | export const addUserToContext = async (userId: string) => { 6 | return new UserProfile({ 7 | id: userId, 8 | roles: ['everyone'], 9 | }); 10 | }; 11 | // This function is called when a user logs in 12 | setAddUserToContext(addUserToContext); 13 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/backend/database.ts: -------------------------------------------------------------------------------- 1 | import { SqliteDriver } from 'mikro-orm-sqlite-wasm'; 2 | import { entities } from './entities'; 3 | 4 | export const connection = { 5 | connectionManagerId: 'sqlite', 6 | mikroOrmConfig: { 7 | entities: entities, 8 | driver: SqliteDriver, 9 | dbName: 'databases/database.sqlite', 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/backend/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sqlite'; 2 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/backend/entities/sqlite/artist.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Album } from './album'; 3 | 4 | @Entity({ tableName: 'Artist' }) 5 | export class Artist { 6 | @PrimaryKey({ fieldName: 'ArtistId', type: 'number' }) 7 | artistId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Album, mappedBy: 'artist' }) 13 | albums = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/backend/entities/sqlite/genre.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'Genre' }) 5 | export class Genre { 6 | @PrimaryKey({ fieldName: 'GenreId', type: 'number' }) 7 | genreId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Track, mappedBy: 'genre' }) 13 | tracks = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/backend/entities/sqlite/media-type.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'MediaType' }) 5 | export class MediaType { 6 | @PrimaryKey({ fieldName: 'MediaTypeId', type: 'number' }) 7 | mediaTypeId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Track, mappedBy: 'mediaType' }) 13 | tracks = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/backend/entities/sqlite/playlist.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, ManyToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'Playlist' }) 5 | export class Playlist { 6 | @PrimaryKey({ fieldName: 'PlaylistId', type: 'number' }) 7 | playlistId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @ManyToMany({ 13 | entity: () => Track, 14 | pivotTable: 'PlaylistTrack', 15 | joinColumn: 'PlaylistId', 16 | inverseJoinColumn: 'TrackId', 17 | }) 18 | tracks = new Collection(this); 19 | } 20 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/backend/index.ts: -------------------------------------------------------------------------------- 1 | import Graphweaver from '@exogee/graphweaver-server'; 2 | 3 | import './auth'; 4 | import './schema'; 5 | 6 | export const graphweaver = new Graphweaver(); 7 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/backend/schema/index.ts: -------------------------------------------------------------------------------- 1 | import './album'; 2 | import './artist'; 3 | import './customer'; 4 | import './employee'; 5 | import './genre'; 6 | import './invoice'; 7 | import './invoice-line'; 8 | import './media-type'; 9 | import './playlist'; 10 | import './track'; 11 | -------------------------------------------------------------------------------- /src/examples/microsoft-entra/src/css-modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.css' { 2 | const content: Record; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /src/examples/okta/databases/database.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/examples/okta/databases/database.sqlite -------------------------------------------------------------------------------- /src/examples/okta/graphweaver-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | adminUI: { 3 | auth: { 4 | primaryMethods: ['OKTA'], 5 | }, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /src/examples/okta/src/admin-ui/custom-pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { WelcomePage } from './welcome-page'; 2 | 3 | export const customPages = { 4 | defaultRoute: '/welcome', 5 | routes: () => [ 6 | { 7 | path: '/welcome', 8 | element: , 9 | }, 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /src/examples/okta/src/admin-ui/custom-pages/welcome-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/okta/src/admin-ui/custom-pages/welcome-page/styles.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | font-size: 2.2rem; 3 | font-weight: bold; 4 | line-height: 3rem; 5 | } 6 | 7 | .list { 8 | list-style: disc; 9 | margin-left: 2rem; 10 | } 11 | 12 | .button { 13 | width: 200px; 14 | justify-content: space-between; 15 | margin-left: auto; 16 | } 17 | 18 | .arrow { 19 | height: 8px; 20 | } 21 | -------------------------------------------------------------------------------- /src/examples/okta/src/backend/auth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './okta'; 2 | -------------------------------------------------------------------------------- /src/examples/okta/src/backend/auth/okta.ts: -------------------------------------------------------------------------------- 1 | import { UserProfile, Okta, setAddUserToContext } from '@exogee/graphweaver-auth'; 2 | 3 | export const okta = new Okta(); 4 | 5 | export const addUserToContext = async (userId: string) => { 6 | return new UserProfile({ 7 | id: userId, 8 | roles: ['everyone'], 9 | }); 10 | }; 11 | // This function is called when a user logs in 12 | setAddUserToContext(addUserToContext); 13 | -------------------------------------------------------------------------------- /src/examples/okta/src/backend/database.ts: -------------------------------------------------------------------------------- 1 | import { SqliteDriver } from 'mikro-orm-sqlite-wasm'; 2 | import { entities } from './entities'; 3 | 4 | export const connection = { 5 | connectionManagerId: 'sqlite', 6 | mikroOrmConfig: { 7 | entities: entities, 8 | driver: SqliteDriver, 9 | dbName: 'databases/database.sqlite', 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /src/examples/okta/src/backend/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sqlite'; 2 | -------------------------------------------------------------------------------- /src/examples/okta/src/backend/entities/sqlite/artist.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Album } from './album'; 3 | 4 | @Entity({ tableName: 'Artist' }) 5 | export class Artist { 6 | @PrimaryKey({ fieldName: 'ArtistId', type: 'number' }) 7 | artistId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Album, mappedBy: 'artist' }) 13 | albums = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/okta/src/backend/entities/sqlite/genre.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'Genre' }) 5 | export class Genre { 6 | @PrimaryKey({ fieldName: 'GenreId', type: 'number' }) 7 | genreId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Track, mappedBy: 'genre' }) 13 | tracks = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/okta/src/backend/entities/sqlite/media-type.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'MediaType' }) 5 | export class MediaType { 6 | @PrimaryKey({ fieldName: 'MediaTypeId', type: 'number' }) 7 | mediaTypeId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Track, mappedBy: 'mediaType' }) 13 | tracks = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/okta/src/backend/entities/sqlite/playlist.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, ManyToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'Playlist' }) 5 | export class Playlist { 6 | @PrimaryKey({ fieldName: 'PlaylistId', type: 'number' }) 7 | playlistId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @ManyToMany({ 13 | entity: () => Track, 14 | pivotTable: 'PlaylistTrack', 15 | joinColumn: 'PlaylistId', 16 | inverseJoinColumn: 'TrackId', 17 | }) 18 | tracks = new Collection(this); 19 | } 20 | -------------------------------------------------------------------------------- /src/examples/okta/src/backend/index.ts: -------------------------------------------------------------------------------- 1 | import Graphweaver from '@exogee/graphweaver-server'; 2 | 3 | import './auth'; 4 | import './schema'; 5 | 6 | export const graphweaver = new Graphweaver(); 7 | -------------------------------------------------------------------------------- /src/examples/okta/src/backend/schema/index.ts: -------------------------------------------------------------------------------- 1 | import './album'; 2 | import './artist'; 3 | import './customer'; 4 | import './employee'; 5 | import './genre'; 6 | import './invoice'; 7 | import './invoice-line'; 8 | import './media-type'; 9 | import './playlist'; 10 | import './track'; 11 | -------------------------------------------------------------------------------- /src/examples/okta/src/css-modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.css' { 2 | const content: Record; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/.env.example: -------------------------------------------------------------------------------- 1 | REST_BASE_URL='https://swapi.info/api' 2 | AUTH_PUBLIC_KEY_PEM_BASE64="base64_encoded_pem_public_key" 3 | AUTH_PRIVATE_KEY_PEM_BASE64="base64_encoded_pem_private_key" 4 | AUTH_BASE_URI="http://localhost:9000" 5 | AUTH_WHITELIST_DOMAINS="localhost" 6 | DATABASE_HOST="localhost" 7 | DATABASE_USERNAME="root" 8 | DATABASE_PASSWORD= 9 | 10 | AUTH_FORGOTTEN_PASSWORD_LINK_RATE_LIMIT='3' 11 | AUTH_FORGOTTEN_PASSWORD_LINK_RATE_PERIOD='1d' 12 | AUTH_FORGOTTEN_PASSWORD_LINK_TTL='4h' -------------------------------------------------------------------------------- /src/examples/rest-with-auth/.gitignore: -------------------------------------------------------------------------------- 1 | # Working build files 2 | .esbuild 3 | .graphweaver 4 | *.pem 5 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/examples/rest-with-auth/graphweaver-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | adminUI: { 3 | auth: { 4 | primaryMethods: ['PASSWORD'], 5 | secondaryMethods: ['API_KEY', 'ONE_TIME_PASSWORD', 'MAGIC_LINK', 'WEB3', 'PASSKEY'], 6 | }, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/scripts/import.sh: -------------------------------------------------------------------------------- 1 | mysql -h$DATABASE_HOST -u$DATABASE_USERNAME --password=$DATABASE_PASSWORD -e "DROP DATABASE IF EXISTS todo_app;" 2 | mysql -h$DATABASE_HOST -u$DATABASE_USERNAME --password=$DATABASE_PASSWORD -e "CREATE DATABASE todo_app;" 3 | mysql -h$DATABASE_HOST -u$DATABASE_USERNAME --password=$DATABASE_PASSWORD todo_app < database.sql -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/admin-ui/custom-fields/index.ts: -------------------------------------------------------------------------------- 1 | import { CustomField } from '@exogee/graphweaver-admin-ui-components'; 2 | 3 | import { Link } from './link'; 4 | 5 | export const customFields = new Map(); 6 | customFields.set('Task', [ 7 | { 8 | name: 'search', 9 | type: 'custom', 10 | index: 3, 11 | component: Link, 12 | hideInDetailForm: true, 13 | }, 14 | ]); 15 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/admin-ui/custom-pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { WelcomePage } from './welcome-page'; 2 | 3 | export const customPages = { 4 | defaultRoute: '/welcome', 5 | routes: () => [ 6 | { 7 | path: '/welcome', 8 | element: , 9 | }, 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/admin-ui/custom-pages/welcome-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/admin-ui/custom-pages/welcome-page/styles.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | font-size: 2.2rem; 3 | font-weight: bold; 4 | line-height: 3rem; 5 | } 6 | 7 | .list { 8 | list-style: disc; 9 | margin-left: 2rem; 10 | } 11 | 12 | .button { 13 | width: 200px; 14 | justify-content: space-between; 15 | margin-left: auto; 16 | } 17 | 18 | .arrow { 19 | height: 8px; 20 | } 21 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/auth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './methods'; 2 | export * from './context'; 3 | export * from './roles'; 4 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/auth/methods/index.ts: -------------------------------------------------------------------------------- 1 | export * from './api-key'; 2 | export * from './password'; 3 | export * from './one-time-password'; 4 | export * from './magic-link'; 5 | export * from './passkey'; 6 | export * from './web3'; 7 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/auth/methods/passkey.ts: -------------------------------------------------------------------------------- 1 | import { Passkey, PasskeyData } from '@exogee/graphweaver-auth'; 2 | import { MikroBackendProvider } from '@exogee/graphweaver-mikroorm'; 3 | 4 | import { Authentication } from '../../entities/mysql'; 5 | import { myConnection } from '../../database'; 6 | 7 | export const passkey = new Passkey({ 8 | dataProvider: new MikroBackendProvider(Authentication, myConnection), 9 | }); 10 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/auth/roles.ts: -------------------------------------------------------------------------------- 1 | import { graphweaverMetadata } from '@exogee/graphweaver'; 2 | 3 | export enum Roles { 4 | LIGHT_SIDE = 'LIGHT_SIDE', 5 | DARK_SIDE = 'DARK_SIDE', 6 | } 7 | 8 | graphweaverMetadata.collectEnumInformation({ 9 | name: 'Roles', 10 | target: Roles, 11 | }); 12 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mysql'; 2 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/entities/mysql/authentication.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryKey, Property, JsonType, BigIntType } from '@mikro-orm/core'; 2 | import type { AuthenticationBaseEntity } from '@exogee/graphweaver-auth'; 3 | 4 | @Entity() 5 | export class Authentication implements AuthenticationBaseEntity { 6 | @PrimaryKey({ type: new BigIntType('string') }) 7 | id!: string; 8 | 9 | @Property({ type: String }) 10 | type!: string; 11 | 12 | @Property({ type: new BigIntType('string') }) 13 | userId!: string; 14 | 15 | @Property({ type: JsonType }) 16 | data!: T; 17 | 18 | @Property({ type: Date }) 19 | createdAt!: Date; 20 | } 21 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/entities/mysql/credential.ts: -------------------------------------------------------------------------------- 1 | import { BigIntType, Entity, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { CredentialStorage } from '@exogee/graphweaver-auth'; 3 | 4 | @Entity() 5 | export class Credential implements CredentialStorage { 6 | @PrimaryKey({ type: new BigIntType('string') }) 7 | id!: string; 8 | 9 | @Property({ type: String }) 10 | username!: string; 11 | 12 | @Property({ type: String }) 13 | password!: string; 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/entities/mysql/index.ts: -------------------------------------------------------------------------------- 1 | export * from './api-key'; 2 | export * from './authentication'; 3 | export * from './credential'; 4 | export * from './tag'; 5 | export * from './task-count-by-tag'; 6 | export * from './task'; 7 | export * from './trace'; 8 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/entities/mysql/tag.ts: -------------------------------------------------------------------------------- 1 | import { BigIntType, Entity, PrimaryKey, Property, ManyToMany, Collection } from '@mikro-orm/core'; 2 | 3 | import { Task } from './task'; 4 | 5 | @Entity() 6 | export class Tag { 7 | @PrimaryKey({ type: new BigIntType('string') }) 8 | id!: string; 9 | 10 | @Property({ type: String }) 11 | name!: string; 12 | 13 | @ManyToMany(() => Task, (task) => task.tags) 14 | tasks = new Collection(this); 15 | } 16 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/index.ts: -------------------------------------------------------------------------------- 1 | import Graphweaver from '@exogee/graphweaver-server'; 2 | import { AuthorizationContext } from '@exogee/graphweaver-auth'; 3 | 4 | import './auth'; 5 | import './schema'; 6 | 7 | import { traceProvider } from './schema/trace'; 8 | 9 | export const graphweaver = new Graphweaver({ 10 | fileAutoGenerationOptions: { 11 | typesOutputPath: ['./'], 12 | }, 13 | openTelemetry: { 14 | traceProvider, 15 | instrumentations: [], 16 | }, 17 | }); 18 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/schema/index.ts: -------------------------------------------------------------------------------- 1 | import './user'; 2 | import './task'; 3 | import './tag'; 4 | import './task-count-by-tag'; 5 | import './trace'; 6 | -------------------------------------------------------------------------------- /src/examples/rest-with-auth/src/backend/schema/trace.ts: -------------------------------------------------------------------------------- 1 | import { Trace } from '@exogee/graphweaver'; 2 | import { MikroBackendProvider } from '@exogee/graphweaver-mikroorm'; 3 | import { ApplyAccessControlList } from '@exogee/graphweaver-auth'; 4 | 5 | import { Trace as OrmTrace } from '../entities'; 6 | import { myConnection } from '../database'; 7 | 8 | export const traceProvider = new MikroBackendProvider(OrmTrace, myConnection); 9 | 10 | ApplyAccessControlList({ 11 | DARK_SIDE: { 12 | // Dark side user role can perform operations on any tag 13 | all: true, 14 | }, 15 | })(Trace); 16 | -------------------------------------------------------------------------------- /src/examples/rest/.gitignore: -------------------------------------------------------------------------------- 1 | # Working build files 2 | .esbuild 3 | .graphweaver 4 | -------------------------------------------------------------------------------- /src/examples/rest/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/examples/rest/README.md: -------------------------------------------------------------------------------- 1 | # Simple REST 2 | 3 | This example connects to the [SWAPI.info API](https://swapi.info). 4 | 5 | ## Start a local development server 6 | 7 | This example has no setup steps required. Just run: 8 | 9 | ``` 10 | pnpm i 11 | pnpm start 12 | ``` 13 | -------------------------------------------------------------------------------- /src/examples/rest/src/backend/index.ts: -------------------------------------------------------------------------------- 1 | import Graphweaver from '@exogee/graphweaver-server'; 2 | 3 | import './schema'; 4 | 5 | export const graphweaver = new Graphweaver(); 6 | -------------------------------------------------------------------------------- /src/examples/rest/src/backend/schema/index.ts: -------------------------------------------------------------------------------- 1 | export * from './person'; 2 | -------------------------------------------------------------------------------- /src/examples/s3-storage/.env.example: -------------------------------------------------------------------------------- 1 | AWS_S3_BUCKET="test" 2 | AWS_S3_ENDPOINT="http://127.0.0.1:9003" 3 | AWS_REGION="us-east-1" 4 | AWS_ACCESS_KEY_ID="REPLACE WITH YOUR ACCESS KEY ID" 5 | AWS_SECRET_ACCESS_KEY="REPLACE WITH YOUR SECRET ACCESS KEY" 6 | PGDATABASE='gw_storage_provider' 7 | PGUSER='postgres' 8 | PGPASSWORD='' 9 | PGPORT=5432 -------------------------------------------------------------------------------- /src/examples/s3-storage/.gitignore: -------------------------------------------------------------------------------- 1 | # Working build files 2 | .esbuild 3 | .graphweaver 4 | -------------------------------------------------------------------------------- /src/examples/s3-storage/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/examples/s3-storage/database.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE "submission" (id SERIAL PRIMARY KEY, image jsonb); 2 | 3 | CREATE TABLE "image_note" ( 4 | id UUID PRIMARY KEY, 5 | submission_id INTEGER REFERENCES submission(id) NOT NULL, 6 | note TEXT NOT NULL 7 | ); 8 | -------------------------------------------------------------------------------- /src/examples/s3-storage/scripts/import.sh: -------------------------------------------------------------------------------- 1 | dropdb gw_storage_provider --force 2 | createdb gw_storage_provider 3 | psql -d gw_storage_provider -f database.sql -------------------------------------------------------------------------------- /src/examples/s3-storage/src/admin-ui/custom-pages/index.tsx: -------------------------------------------------------------------------------- 1 | import type { CustomPageConfiguration } from '@exogee/graphweaver-admin-ui-components'; 2 | import { WelcomePage } from './welcome-page'; 3 | 4 | export const customPages: CustomPageConfiguration = { 5 | defaultRoute: '/welcome', 6 | routes: () => [ 7 | { 8 | path: '/welcome', 9 | element: , 10 | }, 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/admin-ui/custom-pages/welcome-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/admin-ui/custom-pages/welcome-page/styles.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | font-size: 2.2rem; 3 | font-weight: bold; 4 | line-height: 3rem; 5 | } 6 | 7 | .list { 8 | list-style: disc; 9 | margin-left: 2rem; 10 | } 11 | 12 | .button { 13 | width: 200px; 14 | justify-content: space-between; 15 | margin-left: auto; 16 | } 17 | 18 | .arrow { 19 | height: 8px; 20 | } 21 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/backend/database.ts: -------------------------------------------------------------------------------- 1 | import { PostgreSqlDriver } from '@mikro-orm/postgresql'; 2 | 3 | import { ImageNote, Submission } from './entities'; 4 | 5 | export const pgConnection = { 6 | connectionManagerId: 'pg', 7 | mikroOrmConfig: { 8 | entities: [Submission, ImageNote], 9 | driver: PostgreSqlDriver, 10 | dbName: process.env.PGDATABASE, 11 | user: process.env.PGUSER, 12 | password: process.env.PGPASSWORD, 13 | port: process.env.PGPORT ? parseInt(process.env.PGPORT) : 5432, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/backend/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './postgresql'; 2 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/backend/entities/postgresql/image-note.ts: -------------------------------------------------------------------------------- 1 | import { Entity, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Submission } from './submission'; 3 | import { Ref } from '@mikro-orm/core/entity'; 4 | 5 | @Entity() 6 | export class ImageNote { 7 | @PrimaryKey({ type: 'uuid' }) 8 | id!: string; 9 | 10 | @OneToOne({ 11 | entity: () => Submission, 12 | }) 13 | submission!: Ref; 14 | 15 | @Property({ type: 'text' }) 16 | note!: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/backend/entities/postgresql/index.ts: -------------------------------------------------------------------------------- 1 | export * from './submission'; 2 | export * from './image-note'; 3 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/backend/entities/postgresql/submission.ts: -------------------------------------------------------------------------------- 1 | import { BigIntType, Entity, OneToOne, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { ImageNote } from './image-note'; 3 | 4 | @Entity() 5 | export class Submission { 6 | @PrimaryKey({ type: new BigIntType('string') }) 7 | id!: string; 8 | 9 | @Property({ type: 'jsonb', nullable: true }) 10 | image?: { filename: string; type: string }; 11 | 12 | @OneToOne({ entity: () => ImageNote, mappedBy: 'submission', nullable: true }) 13 | imageNote?: ImageNote; 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/backend/index.ts: -------------------------------------------------------------------------------- 1 | import Graphweaver from '@exogee/graphweaver-server'; 2 | 3 | import './custom-mutations'; 4 | import './custom-queries'; 5 | import './schema'; 6 | 7 | export const graphweaver = new Graphweaver(); 8 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/backend/s3-provider.ts: -------------------------------------------------------------------------------- 1 | import { S3StorageProvider, StorageType } from '@exogee/graphweaver-storage-provider'; 2 | 3 | export const s3Provider = new S3StorageProvider({ 4 | bucketName: process.env.AWS_S3_BUCKET, 5 | region: process.env.AWS_REGION, 6 | type: StorageType.S3, 7 | expiresIn: 3600, 8 | endpoint: process.env.AWS_S3_ENDPOINT, 9 | }); 10 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/backend/schema/index.ts: -------------------------------------------------------------------------------- 1 | export * from './submission'; 2 | export * from './image-note'; 3 | -------------------------------------------------------------------------------- /src/examples/s3-storage/src/css-modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.css' { 2 | const content: Record; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /src/examples/sqlite/README.md: -------------------------------------------------------------------------------- 1 | # SQLite Example Graphweaver Project 2 | 3 | ## Making Database changes 4 | 5 | To create a new sqlite database from the sql found in `./databases/database.sql`, run the following command 6 | 7 | `cat databases/database.sql | sqlite3 databases/database.sqlite` 8 | -------------------------------------------------------------------------------- /src/examples/sqlite/databases/database.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/examples/sqlite/databases/database.sqlite -------------------------------------------------------------------------------- /src/examples/sqlite/databases/trace.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/examples/sqlite/databases/trace.sqlite -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/.gitignore: -------------------------------------------------------------------------------- 1 | csv-export-overrides.generated.ts 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/component.tsx: -------------------------------------------------------------------------------- 1 | import { DefaultLayout } from '@exogee/graphweaver-admin-ui-components'; 2 | import { SalesOverTimePerEmployee } from './sales-over-time-per-employee'; 3 | import { GenrePopularity } from './genre-popularity'; 4 | import styles from './styles.module.css'; 5 | 6 | export const Dashboard = () => { 7 | return ( 8 | 9 |
10 |

Sales per employee over time

11 | 12 |

Customer preferences by genre

13 | 14 |
15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/genre-popularity/graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from '@exogee/graphweaver-admin-ui-components'; 2 | 3 | export const genrePopularity = gql` 4 | query genrePopularity { 5 | genres { 6 | genreId 7 | name 8 | tracks { 9 | trackId 10 | invoiceLines { 11 | invoiceLineId 12 | quantity 13 | } 14 | } 15 | tracks_aggregate { 16 | count 17 | } 18 | } 19 | } 20 | `; 21 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/genre-popularity/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/genre-popularity/styles.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | } 4 | 5 | .controlsContainer { 6 | display: flex; 7 | flex-direction: column; 8 | gap: 20px; 9 | min-width: 200px; 10 | } 11 | 12 | .chartContainer { 13 | flex: 1; 14 | height: 35vh; 15 | } 16 | 17 | .controlItem { 18 | display: flex; 19 | flex-direction: column; 20 | } 21 | 22 | .checkBoxContainer { 23 | display: flex; 24 | flex-direction: row; 25 | gap: 10px; 26 | align-items: center; 27 | } 28 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/sales-over-time-per-employee/bar-chart/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/sales-over-time-per-employee/bar-controls/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/sales-over-time-per-employee/bar-controls/styles.module.css: -------------------------------------------------------------------------------- 1 | .controlItem { 2 | display: flex; 3 | flex-direction: column; 4 | } 5 | 6 | .checkBoxContainer { 7 | display: flex; 8 | flex-direction: row; 9 | gap: 10px; 10 | align-items: center; 11 | } 12 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/sales-over-time-per-employee/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/sales-over-time-per-employee/line-chart/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/sales-over-time-per-employee/line-controls/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/sales-over-time-per-employee/line-controls/styles.module.css: -------------------------------------------------------------------------------- 1 | .controlItem { 2 | display: flex; 3 | flex-direction: column; 4 | } 5 | 6 | .checkBoxContainer { 7 | display: flex; 8 | flex-direction: row; 9 | gap: 10px; 10 | align-items: center; 11 | } 12 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/sales-over-time-per-employee/use-data/graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from '@exogee/graphweaver-admin-ui-components'; 2 | 3 | export const salesPerEmployee = gql` 4 | query salesPerEmployee { 5 | employees { 6 | employeeId 7 | firstName 8 | lastName 9 | customers { 10 | customerId 11 | invoices { 12 | invoiceId 13 | invoiceDate 14 | total 15 | } 16 | } 17 | } 18 | } 19 | `; 20 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/sales-over-time-per-employee/use-data/index.ts: -------------------------------------------------------------------------------- 1 | export * from './hook'; 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/sales-over-time-per-employee/utils.ts: -------------------------------------------------------------------------------- 1 | /** year-month. Example: 2025-01 */ 2 | export type DateSlot = string; 3 | export type EmployeeId = string; 4 | export type TotalSales = number; 5 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/dashboard/styles.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | margin-top: 50px; 3 | } 4 | 5 | .container h1 { 6 | margin: 20px 0 30px 0; 7 | } 8 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/index.tsx: -------------------------------------------------------------------------------- 1 | import type { CustomPageConfiguration } from '@exogee/graphweaver-admin-ui-components'; 2 | import { WelcomePage } from './welcome-page'; 3 | import { Dashboard } from './dashboard'; 4 | 5 | export const customPages: CustomPageConfiguration = { 6 | defaultRoute: '/welcome', 7 | routes: () => [ 8 | { 9 | path: '/welcome', 10 | element: , 11 | }, 12 | { 13 | path: '/dashboard', 14 | element: , 15 | }, 16 | ], 17 | 18 | navLinks: async () => { 19 | return [{ name: 'Custom Dashboard', route: '/dashboard' }]; 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/welcome-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/admin-ui/custom-pages/welcome-page/styles.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | font-size: 2.2rem; 3 | font-weight: bold; 4 | line-height: 3rem; 5 | } 6 | 7 | .list { 8 | list-style: disc; 9 | margin-left: 2rem; 10 | } 11 | 12 | .button { 13 | width: 200px; 14 | justify-content: space-between; 15 | margin-left: auto; 16 | } 17 | 18 | .arrow { 19 | height: 8px; 20 | } 21 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/backend/database.ts: -------------------------------------------------------------------------------- 1 | import { SqliteDriver } from 'mikro-orm-sqlite-wasm'; 2 | import { entities, Trace } from './entities'; 3 | 4 | export const connection = { 5 | connectionManagerId: 'sqlite', 6 | mikroOrmConfig: { 7 | entities: entities, 8 | driver: SqliteDriver, 9 | dbName: 'databases/database.sqlite', 10 | }, 11 | }; 12 | 13 | export const traceConnection = { 14 | connectionManagerId: 'sqlite2', 15 | mikroOrmConfig: { 16 | entities: [Trace], 17 | driver: SqliteDriver, 18 | dbName: 'databases/trace.sqlite', 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/backend/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sqlite'; 2 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/backend/entities/sqlite/artist.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Album } from './album'; 3 | 4 | @Entity({ tableName: 'Artist' }) 5 | export class Artist { 6 | @PrimaryKey({ fieldName: 'ArtistId', type: 'number' }) 7 | artistId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Album, mappedBy: 'artist' }) 13 | albums = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/backend/entities/sqlite/genre.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'Genre' }) 5 | export class Genre { 6 | @PrimaryKey({ fieldName: 'GenreId', type: 'number' }) 7 | genreId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Track, mappedBy: 'genre' }) 13 | tracks = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/backend/entities/sqlite/media-type.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, OneToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'MediaType' }) 5 | export class MediaType { 6 | @PrimaryKey({ fieldName: 'MediaTypeId', type: 'number' }) 7 | mediaTypeId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @OneToMany({ entity: () => Track, mappedBy: 'mediaType' }) 13 | tracks = new Collection(this); 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/backend/entities/sqlite/playlist.ts: -------------------------------------------------------------------------------- 1 | import { Collection, Entity, ManyToMany, PrimaryKey, Property } from '@mikro-orm/core'; 2 | import { Track } from './track'; 3 | 4 | @Entity({ tableName: 'Playlist' }) 5 | export class Playlist { 6 | @PrimaryKey({ fieldName: 'PlaylistId', type: 'number' }) 7 | playlistId!: number; 8 | 9 | @Property({ fieldName: 'Name', type: 'NVARCHAR(120)', nullable: true }) 10 | name?: string; 11 | 12 | @ManyToMany({ 13 | entity: () => Track, 14 | pivotTable: 'PlaylistTrack', 15 | joinColumn: 'PlaylistId', 16 | inverseJoinColumn: 'TrackId', 17 | }) 18 | tracks = new Collection(this); 19 | } 20 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/backend/index.ts: -------------------------------------------------------------------------------- 1 | import Graphweaver from '@exogee/graphweaver-server'; 2 | import { MikroBackendProvider } from '@exogee/graphweaver-mikroorm'; 3 | 4 | import './schema'; 5 | 6 | import { traceConnection } from './database'; 7 | import { Trace } from './entities'; 8 | 9 | export const traceProvider = new MikroBackendProvider(Trace, traceConnection); 10 | 11 | export const graphweaver = new Graphweaver({ 12 | openTelemetry: { 13 | traceProvider, 14 | }, 15 | }); 16 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/backend/schema/index.ts: -------------------------------------------------------------------------------- 1 | import './album'; 2 | import './artist'; 3 | import './customer'; 4 | import './employee'; 5 | import './genre'; 6 | import './invoice'; 7 | import './invoice-line'; 8 | import './media-type'; 9 | import './playlist'; 10 | import './total-invoices-by-customer'; 11 | import './track'; 12 | -------------------------------------------------------------------------------- /src/examples/sqlite/src/css-modules.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.module.css' { 2 | const content: Record; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /src/examples/xero/.env.example: -------------------------------------------------------------------------------- 1 | XERO_CLIENT_ID="[value from Xero]" 2 | XERO_CLIENT_SECRET="[value from Xero]" 3 | XERO_CLIENT_REDIRECT_URIS="http://localhost:9000/xero-auth-code" 4 | -------------------------------------------------------------------------------- /src/examples/xero/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ignorePatterns: ['.deploy/**', '.build/**', 'lib/**', 'resolvers-types.ts'], 3 | }; 4 | -------------------------------------------------------------------------------- /src/examples/xero/.gitignore: -------------------------------------------------------------------------------- 1 | # We definitely don't need our Xero access token in Git 2 | token.json 3 | 4 | # Working build files 5 | .esbuild 6 | .graphweaver 7 | -------------------------------------------------------------------------------- /src/examples/xero/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/examples/xero/src/admin-ui/custom-pages/dashboards/all-companies/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/xero/src/admin-ui/custom-pages/dashboards/index.ts: -------------------------------------------------------------------------------- 1 | export * from './all-companies'; 2 | export * from './single-company'; 3 | -------------------------------------------------------------------------------- /src/examples/xero/src/admin-ui/custom-pages/dashboards/single-company/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/xero/src/admin-ui/custom-pages/dashboards/single-company/tooltip.tsx: -------------------------------------------------------------------------------- 1 | import { PointTooltip } from '@nivo/line'; 2 | import styles from './styles.module.css'; 3 | 4 | const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; 5 | 6 | export const tooltip: PointTooltip = ({ point }) => { 7 | const date = new Date(point.data.xFormatted); 8 | 9 | return ( 10 |
11 |

{point.serieId}

12 | 13 | {months[date.getMonth()]} {date.getFullYear()} 14 | 15 | {point.data.yFormatted} 16 |
17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/examples/xero/src/admin-ui/custom-pages/welcome-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/examples/xero/src/admin-ui/custom-pages/welcome-page/styles.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | font-size: 2.2rem; 3 | font-weight: bold; 4 | line-height: 3rem; 5 | } 6 | 7 | .button { 8 | width: 200px; 9 | justify-content: space-between; 10 | margin-left: auto; 11 | } 12 | 13 | .arrow { 14 | height: 8px; 15 | } 16 | -------------------------------------------------------------------------------- /src/examples/xero/src/backend/index.ts: -------------------------------------------------------------------------------- 1 | import Graphweaver from '@exogee/graphweaver-server'; 2 | 3 | import { XeroAuthApolloPlugin } from '@exogee/graphweaver-xero'; 4 | 5 | import './schema'; 6 | 7 | export const graphweaver = new Graphweaver({ 8 | apolloServerOptions: { 9 | plugins: [XeroAuthApolloPlugin], 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /src/examples/xero/src/backend/schema/index.ts: -------------------------------------------------------------------------------- 1 | export * from './account'; 2 | export * from './profit-and-loss-row'; 3 | export * from './tenant'; 4 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ignorePatterns: ['.deploy/**', '.build/**', 'lib/**'], 3 | extends: ["plugin:storybook/recommended"] 4 | }; 5 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/packages/admin-ui-components/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | 4 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/.storybook/manager.ts: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/manager-api'; 2 | import theme from './theme'; 3 | 4 | addons.setConfig({ 5 | theme, 6 | }); 7 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/.storybook/preview.ts: -------------------------------------------------------------------------------- 1 | import type { Preview } from '@storybook/react'; 2 | import './main.css'; 3 | import theme from './theme'; 4 | const preview: Preview = { 5 | parameters: { 6 | controls: { 7 | matchers: { 8 | color: /(background|color)$/i, 9 | date: /Date$/i, 10 | }, 11 | }, 12 | docs: { 13 | theme, 14 | }, 15 | }, 16 | }; 17 | 18 | export default preview; 19 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/@types/auth.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'virtual:graphweaver-auth-ui-components' { 2 | import { JSX } from 'react'; 3 | export const SignOut: () => JSX.Element | null; 4 | export const customFields: Map | undefined; 5 | } 6 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/@types/custom-fields.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'virtual:graphweaver-user-supplied-custom-fields' { 2 | import { CustomField } from '../src'; 3 | 4 | export const customFields: Map | undefined; 5 | } 6 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/@types/custom-pages.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'virtual:graphweaver-user-supplied-custom-pages' { 2 | import { RouteObject } from '@exogee/graphweaver-admin-ui'; 3 | import { JSX } from 'react'; 4 | 5 | export interface NavLinkExport { 6 | name: string; 7 | route: string; 8 | } 9 | 10 | export interface CustomPagesExport { 11 | defaultRoute?: string; 12 | routes: () => RouteObject[] | Promise; 13 | navLinks: () => NavLinkExport[] | Promise; 14 | sidebarFooter: () => JSX.Element | null; 15 | } 16 | 17 | export const customPages: CustomPagesExport; 18 | } 19 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/@types/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/build.js: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild'; 2 | import { copy } from 'esbuild-plugin-copy'; 3 | 4 | (async () => { 5 | const { glob } = await import('glob'); 6 | const entryPoints = await glob('./src/**/*.{ts,tsx,css}'); 7 | 8 | await esbuild.build({ 9 | outdir: 'lib', 10 | outbase: 'src', 11 | format: 'esm', 12 | sourcemap: 'linked', 13 | entryPoints, 14 | loader: { 15 | '.module.css': 'css', 16 | }, 17 | plugins: [ 18 | copy({ 19 | assets: [ 20 | { 21 | from: ['./src/assets/**/*'], 22 | to: ['./assets'], 23 | }, 24 | ], 25 | }), 26 | ], 27 | }); 28 | })(); 29 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/404-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/alert/index.ts: -------------------------------------------------------------------------------- 1 | export type { AlertProps } from './alert'; 2 | export { Alert } from './alert'; 3 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/16-arrow.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const Arrow = (props: SVGProps) => ( 4 | 5 | 12 | 13 | ); 14 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/16-chevron-down.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const ChevronDownIcon = (props: SVGProps) => ( 4 | 5 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/16-logout.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const LogoutIcon = (props: SVGProps) => ( 4 | 5 | 12 | 19 | 20 | ); 21 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/16-search.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const SearchIcon = (props: SVGProps) => ( 4 | 5 | 6 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/16-success.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const SuccessIcon = (props: SVGProps) => ( 4 | 5 | 6 | 7 | ); 8 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/16-table.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const TableIcon = (props: SVGProps) => ( 4 | 5 | 11 | 12 | ); 13 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/16-warning.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const WarningIcon = (props: SVGProps) => ( 4 | 5 | 6 | 7 | ); 8 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/checkmark.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const CheckmarkIcon = (props: SVGProps) => ( 4 | 5 | 12 | 13 | ); 14 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/close-icon.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const CloseIcon = (props: SVGProps) => ( 4 | 5 | 12 | 13 | ); 14 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/menu.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const MenuIcon = (props: SVGProps) => ( 4 | 5 | S ShowMenu 18 N 6 | 7 | 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/assets/success-checkmark.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const SuccessCheckmarkIcon = (props: SVGProps) => ( 4 | 5 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/badge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/button/index.ts: -------------------------------------------------------------------------------- 1 | export type { ButtonProps } from './button'; 2 | export { Button } from './button'; 3 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/card/component.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactNode } from 'react'; 2 | import styles from './styles.module.css'; 3 | 4 | interface CardProps { 5 | title?: string; 6 | description?: string; 7 | children: ReactNode; 8 | } 9 | 10 | export const Card: React.FC = ({ title, description, children }) => { 11 | return ( 12 |
13 | {title &&

{title}

} 14 | {description &&

{description}

} 15 | {children} 16 |
17 | ); 18 | }; 19 | 20 | export default Card; 21 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/card/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/card/styles.module.css: -------------------------------------------------------------------------------- 1 | .card { 2 | background-color: #1e1a25; 3 | border: 1px solid #3b3349; 4 | border-radius: 12px; 5 | padding: 10px; 6 | } 7 | 8 | .description { 9 | color: #666; 10 | } 11 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/checkbox/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/combo-box/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/config.ts: -------------------------------------------------------------------------------- 1 | export const autoFocusDelay = 600; 2 | export const graphweaverLogo = 'https://graphweaver.com/logo.svg'; 3 | export const localStorageAuthKey = 'graphweaver-auth'; 4 | export const uri = import.meta.env.VITE_GRAPHWEAVER_API_URL || 'http://localhost:9001/'; 5 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/custom-page-config.ts: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | 3 | export interface CustomNavLinkConfiguration { 4 | name: string; 5 | route: string; 6 | } 7 | 8 | export interface CustomRouteConfiguration { 9 | path: string; 10 | element: ReactNode; 11 | } 12 | 13 | export interface CustomPageConfiguration { 14 | defaultRoute?: string; 15 | sidebarFooter?: () => ReactNode; 16 | navLinks?: () => CustomNavLinkConfiguration[] | Promise; 17 | routes?: () => CustomRouteConfiguration[] | Promise; 18 | } 19 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/date-picker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/default-error-fallback/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/detail-panel-field-label/component.tsx: -------------------------------------------------------------------------------- 1 | import styles from './styles.module.css'; 2 | 3 | export const DetailPanelFieldLabel = ({ 4 | fieldName, 5 | required, 6 | }: { 7 | fieldName: string; 8 | required?: boolean; 9 | }) => ( 10 | 18 | ); 19 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/detail-panel-field-label/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/detail-panel-field-label/styles.module.css: -------------------------------------------------------------------------------- 1 | .detailPanelFieldLabel { 2 | flex: none; 3 | 4 | font-family: 'Inter', sans-serif; 5 | font-style: normal; 6 | font-size: 14px; 7 | line-height: 150%; 8 | /* identical to box height, or 21px */ 9 | 10 | color: rgba(237, 232, 242, 0.6); 11 | font-weight: 600; 12 | } 13 | 14 | .required { 15 | font-family: 'Inter', sans-serif; 16 | font-style: normal; 17 | font-size: 14px; 18 | line-height: 150%; 19 | color: rgba(237, 232, 242, 0.6); 20 | font-weight: 600; 21 | } 22 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/detail-panel/fields/index.ts: -------------------------------------------------------------------------------- 1 | export * from './boolean-field'; 2 | export * from './date-field'; 3 | export * from './enum-field'; 4 | export * from './json-field'; 5 | export * from './link-field'; 6 | export * from './relationship-field'; 7 | export * from './media-field'; 8 | export * from './text-field'; 9 | export * from './rich-text-field/index'; 10 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/detail-panel/fields/media-field/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/detail-panel/fields/media-field/styles.module.css: -------------------------------------------------------------------------------- 1 | .row { 2 | display: flex; 3 | flex-direction: row; 4 | justify-content: space-between; 5 | align-items: center; 6 | margin-bottom: 16px; 7 | } 8 | 9 | .fileInput::file-selector-button { 10 | cursor: pointer; 11 | 12 | /* Button styles */ 13 | background: var(--primary-color); 14 | border: 1px solid rgba(237, 232, 242, 0.2); 15 | box-shadow: 0 1px 3px rgba(9, 5, 16, 0.1); 16 | border-radius: 6px; 17 | font-weight: 500; 18 | padding: 8px 12px; 19 | } 20 | 21 | .fileInput::file-selector-button:hover { 22 | background-color: var(--secondary-color); 23 | } 24 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/detail-panel/fields/rich-text-field/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/detail-panel/fields/rich-text-field/menu-bar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/detail-panel/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | export { useDataTransform } from './use-data-transform'; 3 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/detail-panel/use-data-transform.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { EntityField } from '../utils'; 3 | 4 | export interface DataTransform { 5 | field: EntityField; 6 | transform: (value: T) => T | Promise; 7 | } 8 | 9 | export const dataTransforms: Record> = {}; 10 | 11 | export const useDataTransform = (transform: DataTransform) => { 12 | useEffect(() => { 13 | dataTransforms[transform.field.name] = transform; 14 | 15 | return () => { 16 | delete dataTransforms[transform.field.name]; 17 | }; 18 | }, []); 19 | }; 20 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/entity-list/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/error-view/component.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from 'wouter'; 2 | import { RequestIcon } from '../assets/request'; 3 | import styles from './styles.module.css'; 4 | import { Spacer } from '../spacer'; 5 | import { Button } from '../button'; 6 | 7 | export const ErrorView = ({ message }: { message: string }) => { 8 | return ( 9 |
10 | 11 |

Request Error

12 | {message} 13 | 14 | 15 | 16 | 17 |
18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/error-view/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/error-view/styles.module.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: center; 6 | height: 100%; 7 | gap: 18px; 8 | } 9 | 10 | .dataSourceIcon { 11 | width: 64px; 12 | } 13 | 14 | .title { 15 | font-family: 'Inter', sans-serif; 16 | font-weight: 600; 17 | font-size: 32px; 18 | line-height: 140%; 19 | color: #ede8f2; 20 | } 21 | 22 | .text { 23 | background-color: #080214; 24 | padding: 16px; 25 | border-radius: 12px; 26 | color: #ffffff57; 27 | } 28 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/export-modal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/export-modal/styles.module.css: -------------------------------------------------------------------------------- 1 | .exportContainer { 2 | background: var(--detail-bg-color); 3 | border: 1px solid var(--detail-border-color); 4 | border-radius: 6px; 5 | padding: 0 30px; 6 | } 7 | 8 | .contentContainer { 9 | display: flex; 10 | flex-direction: column; 11 | gap: 20px; 12 | padding: 20px 0; 13 | } 14 | 15 | .buttonContainer { 16 | display: flex; 17 | justify-content: flex-start; 18 | } 19 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/filter-bar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/filter-bar/styles.module.css: -------------------------------------------------------------------------------- 1 | .filterBarWrapper { 2 | display: flex; 3 | flex-direction: row; 4 | padding: 16px 0; 5 | gap: 12px; 6 | min-height: 38px; 7 | align-items: center; 8 | } 9 | 10 | @media only screen and (max-width: 1200px) { 11 | .filterBarWrapper { 12 | flex-wrap: wrap; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/filters/index.ts: -------------------------------------------------------------------------------- 1 | export * from './boolean-filter'; 2 | export * from './date-range-filter'; 3 | export * from './dropdown-text-filter'; 4 | export * from './enum-filter'; 5 | export * from './numeric-filter'; 6 | export * from './numeric-range-filter'; 7 | export * from './relationship-filter'; 8 | export * from './text-filter'; 9 | export * from './utils'; 10 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/filters/numeric-range-filter/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/filters/numeric-range-filter/utils.ts: -------------------------------------------------------------------------------- 1 | export const isDefined = (value: T | undefined | null): value is T => 2 | value !== undefined && value !== null; 3 | 4 | export const getNumberOrUndefined = (value: unknown) => { 5 | if (!isDefined(value)) return undefined; 6 | if (typeof value === 'string' && value.trim().length === 0) return undefined; 7 | try { 8 | const number = Number(value); 9 | return isNaN(number) ? undefined : number; 10 | } catch (e) { 11 | console.error('Failed to parse number', e); 12 | return undefined; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/form/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/graphql-viewer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/header/component.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | import styles from './styles.module.css'; 3 | 4 | export interface HeaderProps { 5 | children?: ReactNode; 6 | } 7 | 8 | export const Header = ({ children }: HeaderProps) => ( 9 |
10 |
{children}
11 |
12 | ); 13 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/header/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/header/styles.module.css: -------------------------------------------------------------------------------- 1 | .header { 2 | display: flex; 3 | position: relative; 4 | } 5 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './use-debounce'; 2 | export * from './use-auto-focus'; 3 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/hooks/use-auto-focus.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | import { autoFocusDelay } from '../config'; 3 | 4 | export const useAutoFocus = (autoFocus?: boolean) => { 5 | const ref = useRef(null); 6 | 7 | useEffect(() => { 8 | if (autoFocus) setTimeout(() => ref.current?.focus(), autoFocusDelay); 9 | }, [autoFocus]); 10 | 11 | return ref; 12 | }; 13 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/hooks/use-debounce.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | export const useDebounce = (value: T, setter: (value: T) => any, delay: number = 500) => { 4 | useEffect(() => { 5 | const timer = setTimeout(() => setter(value), delay); 6 | 7 | return () => { 8 | clearTimeout(timer); 9 | }; 10 | }, [value, delay]); 11 | }; 12 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/input/index.ts: -------------------------------------------------------------------------------- 1 | export { Input } from './component'; 2 | export type { InputProps } from './component'; 3 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/json-viewer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/layouts/col/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/layouts/default/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/layouts/grid/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/layouts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './default'; 2 | export * from './row'; 3 | export * from './col'; 4 | export * from './grid'; 5 | export * from './page'; 6 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/layouts/page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/layouts/row/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/list-toolbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/loader/component.tsx: -------------------------------------------------------------------------------- 1 | import styles from './styles.module.css'; 2 | 3 | export const Loader = () => ( 4 |
5 |
14 |
15 | ); 16 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/loader/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/missing-entity/component.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from 'wouter'; 2 | import { DataSourcesIcon } from '../assets/64-data-sources'; 3 | import styles from './styles.module.css'; 4 | import { Spacer } from '../spacer'; 5 | 6 | export const MissingEntity = ({ entity }: { entity: string }) => { 7 | return ( 8 |
9 | 10 | 11 |

No such entity: {entity}

12 | 13 | 14 | Return to home 15 | 16 |
17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/missing-entity/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/missing-entity/styles.module.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: center; 6 | height: 100%; 7 | } 8 | 9 | .dataSourceIcon { 10 | width: 64px; 11 | } 12 | 13 | .heading { 14 | font-family: 'Inter', sans-serif; 15 | font-weight: 600; 16 | font-size: 32px; 17 | line-height: 140%; 18 | color: #ede8f2; 19 | } 20 | 21 | .text { 22 | font-family: 'Inter', sans-serif; 23 | font-weight: 400; 24 | font-size: 14px; 25 | line-height: 150%; 26 | color: rgba(237, 232, 242, 0.6); 27 | } 28 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/modal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/playground/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/popover/index.ts: -------------------------------------------------------------------------------- 1 | export type { PopoverItem, PopoverProps } from './component'; 2 | export { Popover } from './component'; 3 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/popoverMenu/index.ts: -------------------------------------------------------------------------------- 1 | export { PopoverMenu } from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/require-schema/component.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | import { useSchema } from '../utils'; 3 | import { Spinner } from '../spinner'; 4 | 5 | export interface RequireSchemaProps { 6 | children?: ReactNode; 7 | } 8 | 9 | export const RequireSchema = ({ children }: RequireSchemaProps) => { 10 | const { loading, error } = useSchema(); 11 | 12 | if (error) return
{error.message}
; 13 | 14 | // If we're still loading, return the spinner, else, we're ready to go. 15 | return loading ? : <>{children}; 16 | }; 17 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/require-schema/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/select/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/selection-bar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/side-bar/contents/dashboard-row.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx'; 2 | import { Link, useRoute } from 'wouter'; 3 | 4 | import { TableIcon } from '../../assets'; 5 | 6 | import styles from '../styles.module.css'; 7 | 8 | export const DashboardRow = ({ 9 | name, 10 | route, 11 | end, 12 | }: { 13 | name: string; 14 | route: string; 15 | end?: boolean; 16 | }) => { 17 | const [isActive] = useRoute(end ? route : `${route}/*?`); 18 | 19 | return ( 20 |
  • 21 | 22 | 23 | {name} 24 | 25 |
  • 26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/side-bar/contents/index.ts: -------------------------------------------------------------------------------- 1 | export * from './backend-row'; 2 | export * from './dashboard-row'; 3 | export * from './entity-row'; 4 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/side-bar/graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | export const TENANTS_QUERY = gql` 4 | query TenantsQueryForSidebar { 5 | result: tenants { 6 | id 7 | tenantName 8 | } 9 | } 10 | `; 11 | 12 | export interface TenantsResult { 13 | result: { 14 | id: string; 15 | tenantName: string; 16 | }[]; 17 | } 18 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/side-bar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/spacer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/spinner/component.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx'; 2 | import styles from './styles.module.css'; 3 | 4 | export enum SpinnerSize { 5 | LARGE = 'LARGE', 6 | SMALL = 'SMALL', 7 | } 8 | 9 | type Props = { 10 | size?: SpinnerSize; 11 | }; 12 | 13 | export const Spinner = ({ size = SpinnerSize.LARGE }: Props) => { 14 | return ( 15 |
    19 |
    20 |
    21 |
    22 |
    23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/spinner/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/star-field/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/star-field/small-star.tsx: -------------------------------------------------------------------------------- 1 | import { DetailedHTMLProps, HTMLAttributes } from 'react'; 2 | 3 | export const SmallStar = ( 4 | props: DetailedHTMLProps, HTMLDivElement> 5 | ) => ( 6 |
    7 |
    16 |
    17 | ); 18 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/switch/index.ts: -------------------------------------------------------------------------------- 1 | export { Switch } from './component'; 2 | export type { SwitchProps } from './component'; 3 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/table/cells/boolean.tsx: -------------------------------------------------------------------------------- 1 | export const BooleanCell = (value: boolean) => `${value}`; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/table/cells/index.ts: -------------------------------------------------------------------------------- 1 | import { BooleanCell } from './boolean'; 2 | import { JsonCell } from './json'; 3 | import { MediaCell } from './media'; 4 | import { NanoDurationCell } from './nano-duration'; 5 | import { NanoTimestampCell } from './nano-timestamp'; 6 | 7 | export const cells = { 8 | JSON: JsonCell, 9 | Boolean: BooleanCell, 10 | NanoDuration: NanoDurationCell, 11 | NanoTimestamp: NanoTimestampCell, 12 | GraphweaverMedia: MediaCell, 13 | }; 14 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/table/cells/json.tsx: -------------------------------------------------------------------------------- 1 | export const JsonCell = (value: any) =>
    {JSON.stringify(value)}
    ; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/table/cells/nano-duration.tsx: -------------------------------------------------------------------------------- 1 | import { UnixNanoTimestamp } from '../../utils'; 2 | 3 | export const NanoDurationCell = (value: any) => { 4 | const duration = UnixNanoTimestamp.fromString(value); 5 | const { value: displayValue, unit } = duration.toSIUnits(); 6 | return ( 7 | 8 | {Number(displayValue).toFixed(2)} {unit} 9 | 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/table/cells/nano-timestamp.tsx: -------------------------------------------------------------------------------- 1 | import { UnixNanoTimestamp } from '../../utils'; 2 | 3 | export const NanoTimestampCell = (value: any) => { 4 | const timestamp = UnixNanoTimestamp.fromString(value); 5 | return {timestamp.toDate().toLocaleString()}; 6 | }; 7 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/table/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/title-bar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/toast/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/toast/styles.module.css: -------------------------------------------------------------------------------- 1 | .toastContainer { 2 | display: flex; 3 | flex-direction: row; 4 | align-items: flex-start; 5 | justify-content: center; 6 | width: 320px; 7 | } 8 | 9 | .iconContainer { 10 | margin-top: 4px; 11 | cursor: pointer; 12 | } 13 | 14 | .iconContainer:hover { 15 | opacity: 0.7; 16 | } 17 | 18 | .closeIconWrapper { 19 | width: 100%; 20 | } 21 | 22 | div[role='status'][aria-live='polite'] { 23 | justify-content: flex-start; 24 | } 25 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/toolbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/toolbar/styles.module.css: -------------------------------------------------------------------------------- 1 | .toolBarContainer { 2 | display: flex; 3 | flex-direction: column; 4 | width: 100%; 5 | } 6 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/trace-viewer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './data-loading'; 2 | export * from './graphql'; 3 | export * from './route-for'; 4 | export * from './timestamp'; 5 | export * from './trace-to-tree'; 6 | export * from './use-schema'; 7 | export * from './use-selected-entity'; 8 | export * from './utils'; 9 | export * from './export-csv'; 10 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/utils/use-selected-entity.ts: -------------------------------------------------------------------------------- 1 | import { useParams } from 'wouter'; 2 | import { useSchema } from './use-schema'; 3 | 4 | export const useSelectedEntity = () => { 5 | const { entity, id } = useParams(); 6 | const { entityByName } = useSchema(); 7 | 8 | if (!entity) return {}; 9 | 10 | const selectedEntity = entityByName(entity); 11 | if (!selectedEntity) return {}; 12 | 13 | return { selectedEntity, selectedEntityId: id }; 14 | }; 15 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/src/welcome-page/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "allowSyntheticDefaultImports": true, 5 | "target": "ESNext", 6 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 7 | "module": "ESNext", 8 | "jsx": "react-jsx", 9 | "outDir": "./lib", 10 | "rootDir": "./src", 11 | "types": ["vite/client"] 12 | }, 13 | "include": ["./src", "./@types"], 14 | "exclude": ["src/**/*.test.ts"], 15 | "references": [{ "path": "../apollo-client" }] 16 | } 17 | -------------------------------------------------------------------------------- /src/packages/admin-ui-components/vite.config.ts: -------------------------------------------------------------------------------- 1 | // vite.config.ts 2 | import { defineConfig } from 'vitest/config'; 3 | import graphweaverPluginImport from 'vite-plugin-graphweaver'; 4 | 5 | const graphweaverPlugin = (graphweaverPluginImport as any) 6 | .default as typeof graphweaverPluginImport; 7 | 8 | export default defineConfig({ 9 | test: { 10 | globals: true, // auto imports describe etc. 11 | include: ['./src/**/*.test.ts'], 12 | }, 13 | plugins: [graphweaverPlugin()], 14 | }); 15 | -------------------------------------------------------------------------------- /src/packages/admin-ui/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/packages/admin-ui/.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /src/packages/admin-ui/@types/auth.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'virtual:graphweaver-auth-ui-components' { 2 | import { RouteObject } from 'graphweaver-admin-ui'; 3 | 4 | export const loadRoutes: () => RouteObject[]; 5 | } 6 | -------------------------------------------------------------------------------- /src/packages/admin-ui/@types/custom-pages.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'virtual:graphweaver-user-supplied-custom-pages' { 2 | import { RouteObject } from '@exogee/graphweaver-admin-ui'; 3 | import type { LoginProps } from '@exogee/graphweaver-admin-ui-components'; 4 | 5 | export interface NavLinkExport { 6 | name: string; 7 | route: string; 8 | } 9 | 10 | export interface CustomPagesExport { 11 | defaultRoute?: string; 12 | routes: () => RouteObject[] | Promise; 13 | navLinks: () => NavLinkExport[] | Promise; 14 | loginProps?: LoginProps; 15 | } 16 | 17 | export const customPages: CustomPagesExport; 18 | } 19 | -------------------------------------------------------------------------------- /src/packages/admin-ui/@types/global.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.css' { 2 | const content: Record; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /src/packages/admin-ui/@types/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createRoot } from 'react-dom/client'; 3 | import { ApolloProvider } from '@apollo/client'; 4 | import { apolloClient, DismissibleToast } from '@exogee/graphweaver-admin-ui-components'; 5 | 6 | import { Router } from './router'; 7 | 8 | import './reset.css'; 9 | import './main.css'; 10 | 11 | createRoot(document.getElementById('root') as HTMLElement).render( 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/analytics/graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from '@apollo/client'; 2 | 3 | export const queryForTrace = gql` 4 | query TracesList($id: String!) { 5 | traces(filter: { traceId: $id }, pagination: { orderBy: { timestamp: ASC } }) { 6 | id 7 | spanId 8 | traceId 9 | parentId 10 | name 11 | timestamp 12 | duration 13 | attributes 14 | } 15 | } 16 | `; 17 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/analytics/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/analytics/styles.module.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | display: flex; 3 | flex-direction: column; 4 | flex-grow: 1; 5 | width: 100%; 6 | height: 100%; 7 | gap: 20px; 8 | } 9 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/index.ts: -------------------------------------------------------------------------------- 1 | export * from './analytics'; 2 | export * from './list'; 3 | export * from './root'; 4 | export * from './playground'; 5 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/list/component.tsx: -------------------------------------------------------------------------------- 1 | import { useParams } from 'wouter'; 2 | import { useSchema, EntityList, MissingEntity } from '@exogee/graphweaver-admin-ui-components'; 3 | 4 | export const List = ({ children }: { children: React.ReactNode }) => { 5 | const { entity } = useParams(); 6 | const { entityByName } = useSchema(); 7 | 8 | if (!entity) throw new Error('There should always be an entity at this point.'); 9 | 10 | if (!entityByName(entity)) { 11 | return ; 12 | } 13 | 14 | return {children}; 15 | }; 16 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/list/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/playground/component.tsx: -------------------------------------------------------------------------------- 1 | import { Playground as PlaygroundComponent } from '@exogee/graphweaver-admin-ui-components'; 2 | 3 | export const Playground = () => ; 4 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/playground/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/root/component.tsx: -------------------------------------------------------------------------------- 1 | import styles from './styles.module.css'; 2 | 3 | export const Root = () =>
    Select an entity to get started
    ; 4 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/root/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/admin-ui/src/pages/root/styles.module.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | display: flex; 3 | flex: 1 1 auto; 4 | align-items: center; 5 | justify-content: center; 6 | 7 | font-size: 24px; 8 | } 9 | -------------------------------------------------------------------------------- /src/packages/apollo-client/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ignorePatterns: ['.deploy/**', '.build/**', 'lib/**'], 3 | }; 4 | -------------------------------------------------------------------------------- /src/packages/apollo-client/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/packages/apollo-client/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | 4 | -------------------------------------------------------------------------------- /src/packages/apollo-client/build.js: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild'; 2 | (async () => { 3 | await esbuild.build({ 4 | outdir: 'lib', 5 | format: 'esm', 6 | sourcemap: 'linked', 7 | entryPoints: ['src/index.ts'], 8 | }); 9 | })(); 10 | -------------------------------------------------------------------------------- /src/packages/apollo-client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "allowSyntheticDefaultImports": true, 5 | "target": "ESNext", 6 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 7 | "module": "ESNext", 8 | "jsx": "react-jsx", 9 | "outDir": "./lib", 10 | "rootDir": "./src" 11 | }, 12 | "include": ["./src"], 13 | "exclude": ["src/**/*.test.ts"] 14 | } 15 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ignorePatterns: ['.deploy/**', '.build/**', 'lib/**'], 3 | }; 4 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/packages/auth-ui-components/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | 4 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/build.js: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild'; 2 | 3 | (async () => { 4 | const { glob } = await import('glob'); 5 | const entryPoints = await glob('./src/**/*.{ts,tsx,css}'); 6 | 7 | await esbuild.build({ 8 | outdir: 'lib', 9 | outbase: 'src', 10 | format: 'esm', 11 | sourcemap: 'linked', 12 | entryPoints, 13 | loader: { 14 | '.module.css': 'css', 15 | }, 16 | }); 17 | })(); 18 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/assets/16-logout.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export const LogoutIcon = (props: SVGProps) => ( 4 | 5 | 12 | 19 | 20 | ); 21 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/assets/index.ts: -------------------------------------------------------------------------------- 1 | export { LogoutIcon } from './16-logout'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/auth-zero/index.ts: -------------------------------------------------------------------------------- 1 | export * from './login'; 2 | export * from './logout'; 3 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/auth-zero/login/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/auth-zero/logout/component.tsx: -------------------------------------------------------------------------------- 1 | import { Logout } from '../../logout'; 2 | import { getAuth0Client } from '../client'; 3 | 4 | type Auth0LogoutProps = { 5 | redirectTo?: string; 6 | }; 7 | 8 | export const Auth0Logout = ({ redirectTo }: Auth0LogoutProps) => { 9 | const handleLogout = async () => { 10 | const client = await getAuth0Client(); 11 | await client.logout({ 12 | logoutParams: { returnTo: redirectTo ?? window.location.origin }, 13 | }); 14 | }; 15 | 16 | return ; 17 | }; 18 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/auth-zero/logout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auth-zero'; 2 | export * from './password'; 3 | export * from './magic-link'; 4 | export * from './microsoft-entra'; 5 | export * from './okta'; 6 | export * from './one-time-password'; 7 | export * from './web3'; 8 | export * from './passkey'; 9 | export * from './secret'; 10 | export * from './logout'; 11 | export * from './sign-out'; 12 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/logout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/logout/styles.module.css: -------------------------------------------------------------------------------- 1 | .buttonContainer { 2 | height: 28px; 3 | left: 8px; 4 | padding: 0px 16px; 5 | border-radius: 6px; 6 | } 7 | 8 | .logoutButton, 9 | .logoutButton:hover { 10 | padding: 0; 11 | border: none; 12 | background: none; 13 | } 14 | 15 | .logoutButton:hover { 16 | text-decoration: underline; 17 | } 18 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/magic-link/challenge/graphql.ts: -------------------------------------------------------------------------------- 1 | import { DocumentNode, gql } from '@apollo/client'; 2 | 3 | export const SEND_MAGIC_LINK_MUTATION: DocumentNode = gql` 4 | mutation { 5 | sendChallengeMagicLink 6 | } 7 | `; 8 | 9 | export const VERIFY_MAGIC_LINK_MUTATION: DocumentNode = gql` 10 | mutation verifyChallengeMagicLink($token: String!) { 11 | result: verifyChallengeMagicLink(token: $token) { 12 | authToken 13 | } 14 | } 15 | `; 16 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/magic-link/challenge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/magic-link/index.ts: -------------------------------------------------------------------------------- 1 | export * from './login'; 2 | export * from './challenge'; 3 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/magic-link/login/graphql.ts: -------------------------------------------------------------------------------- 1 | import { DocumentNode, gql } from '@apollo/client'; 2 | 3 | export const SEND_MAGIC_LINK_MUTATION: DocumentNode = gql` 4 | mutation sendLoginMagicLink($username: String!) { 5 | sendLoginMagicLink(username: $username) 6 | } 7 | `; 8 | 9 | export const VERIFY_MAGIC_LINK_MUTATION: DocumentNode = gql` 10 | mutation verifyLoginMagicLink($username: String!, $token: String!) { 11 | result: verifyLoginMagicLink(username: $username, token: $token) { 12 | authToken 13 | } 14 | } 15 | `; 16 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/magic-link/login/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/microsoft-entra/client.tsx: -------------------------------------------------------------------------------- 1 | import { PublicClientApplication } from '@azure/msal-browser'; 2 | 3 | export const publicClientApplication = new PublicClientApplication({ 4 | auth: { 5 | clientId: import.meta.env.VITE_MICROSOFT_ENTRA_CLIENT_ID, 6 | authority: import.meta.env.VITE_MICROSOFT_ENTRA_TENANT_ID 7 | ? `https://login.microsoftonline.com/${import.meta.env.VITE_MICROSOFT_ENTRA_TENANT_ID}` 8 | : undefined, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/microsoft-entra/index.ts: -------------------------------------------------------------------------------- 1 | export * from './login'; 2 | export * from './logout'; 3 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/microsoft-entra/login/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/microsoft-entra/logout/component.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import { Logout } from '../../logout'; 3 | import { publicClientApplication } from '../client'; 4 | 5 | export interface MicrosoftEntraLogoutProps { 6 | redirectTo?: string; 7 | } 8 | 9 | export const MicrosoftEntraLogout = ({ redirectTo }: MicrosoftEntraLogoutProps) => { 10 | const handleLogout = useCallback( 11 | () => publicClientApplication.logoutRedirect({ postLogoutRedirectUri: redirectTo }), 12 | [] 13 | ); 14 | 15 | return ; 16 | }; 17 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/microsoft-entra/logout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/okta/client.tsx: -------------------------------------------------------------------------------- 1 | import { OktaAuth } from '@okta/okta-auth-js'; 2 | 3 | const clientId = import.meta.env.VITE_OKTA_CLIENT_ID || ''; 4 | const oktaDomain = import.meta.env.VITE_OKTA_DOMAIN || ''; 5 | const issuer = import.meta.env.VITE_OKTA_ISSUER || `https://${oktaDomain}`; 6 | 7 | export const okta = !oktaDomain 8 | ? null 9 | : new OktaAuth({ 10 | issuer, 11 | clientId, 12 | pkce: true, 13 | }); 14 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/okta/index.ts: -------------------------------------------------------------------------------- 1 | export * from './login'; 2 | export * from './logout'; 3 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/okta/login/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/okta/logout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/one-time-password/challenge/graphql.ts: -------------------------------------------------------------------------------- 1 | import { DocumentNode, gql } from '@apollo/client'; 2 | 3 | export const SEND_OTP_MUTATION: DocumentNode = gql` 4 | mutation { 5 | sendOTPChallenge 6 | } 7 | `; 8 | 9 | export const VERIFY_OTP_MUTATION: DocumentNode = gql` 10 | mutation verifyOTPChallenge($code: String!) { 11 | result: verifyOTPChallenge(code: $code) { 12 | authToken 13 | } 14 | } 15 | `; 16 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/one-time-password/challenge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/one-time-password/index.ts: -------------------------------------------------------------------------------- 1 | export * from './challenge'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/passkey/challenge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/passkey/index.ts: -------------------------------------------------------------------------------- 1 | export * from './challenge'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/challenge/graphql.ts: -------------------------------------------------------------------------------- 1 | import { DocumentNode, gql } from '@apollo/client'; 2 | 3 | export const CHALLENGE_MUTATION: DocumentNode = gql` 4 | mutation challengePassword($password: String!) { 5 | result: challengePassword(password: $password) { 6 | authToken 7 | } 8 | } 9 | `; 10 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/challenge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/forgotten-password/graphql.ts: -------------------------------------------------------------------------------- 1 | import { DocumentNode, gql } from '@apollo/client'; 2 | 3 | export const SEND_FORGOTTEN_PASSWORD_LINK: DocumentNode = gql` 4 | mutation sendResetPasswordLink($username: String!) { 5 | result: sendResetPasswordLink(username: $username) 6 | } 7 | `; 8 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/forgotten-password/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/index.ts: -------------------------------------------------------------------------------- 1 | export * from './challenge'; 2 | export * from './login'; 3 | export * from './password'; 4 | export * from './forgotten-password'; 5 | export * from './reset-password'; 6 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/login/graphql.ts: -------------------------------------------------------------------------------- 1 | import { DocumentNode, gql } from '@apollo/client'; 2 | 3 | export const LOGIN_MUTATION: DocumentNode = gql` 4 | mutation loginPassword($username: String!, $password: String!) { 5 | result: loginPassword(username: $username, password: $password) { 6 | authToken 7 | } 8 | } 9 | `; 10 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/login/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/password/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/password/styles.module.css: -------------------------------------------------------------------------------- 1 | .textInputField { 2 | box-sizing: border-box; 3 | height: 40px; 4 | background: rgba(237, 232, 242, 0.02); 5 | border: 1px solid var(--detail-border-color); 6 | border-radius: 6px; 7 | padding: 10px; 8 | width: 100%; 9 | } 10 | 11 | .fieldLabel { 12 | flex: none; 13 | 14 | font-family: 'Inter', sans-serif; 15 | font-style: normal; 16 | font-size: 14px; 17 | line-height: 150%; 18 | /* identical to box height, or 21px */ 19 | 20 | color: rgba(237, 232, 242, 0.6); 21 | font-weight: 600; 22 | } 23 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/reset-password/graphql.ts: -------------------------------------------------------------------------------- 1 | import { DocumentNode, gql } from '@apollo/client'; 2 | 3 | export const RESET_PASSWORD: DocumentNode = gql` 4 | mutation resetPassword($password: String!, $token: String!) { 5 | result: resetPassword(password: $password, token: $token) 6 | } 7 | `; 8 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/password/reset-password/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/secret/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/sign-out/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/web3/challenge/graphql.ts: -------------------------------------------------------------------------------- 1 | import { DocumentNode, gql } from '@apollo/client'; 2 | 3 | export const VERIFY_WEB3_MUTATION: DocumentNode = gql` 4 | mutation verifyWeb3Challenge($token: String!) { 5 | result: verifyWeb3Challenge(token: $token) { 6 | authToken 7 | } 8 | } 9 | `; 10 | 11 | export const ENROL_WALLET_MUTATION: DocumentNode = gql` 12 | mutation enrolWallet($token: String!) { 13 | result: enrolWallet(token: $token) 14 | } 15 | `; 16 | 17 | export const CAN_ENROL_WALLET_QUERY: DocumentNode = gql` 18 | query { 19 | canEnrolWallet 20 | } 21 | `; 22 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/web3/challenge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/components/web3/index.ts: -------------------------------------------------------------------------------- 1 | export * from './challenge'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/globals.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.css'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components'; 2 | export * from './pages'; 3 | export * from './routes'; 4 | export * from './fields'; 5 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/pages/auth/component.tsx: -------------------------------------------------------------------------------- 1 | import { Spacer } from '@exogee/graphweaver-admin-ui-components'; 2 | 3 | import styles from './styles.module.css'; 4 | 5 | export const Auth = ({ children }: { children: React.ReactNode }) => { 6 | return ( 7 |
    8 |
    {children}
    9 | 10 | 11 |
    12 |
    13 | Powered by{' '} 14 | 15 | Graphweaver 16 | 17 |
    18 |
    19 |
    20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/pages/auth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/pages/challenge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component'; 2 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/pages/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auth'; 2 | export * from './challenge'; 3 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/types.ts: -------------------------------------------------------------------------------- 1 | export enum AuthenticationMethod { 2 | MAGIC_LINK = 'mgl', 3 | ONE_TIME_PASSWORD = 'otp', 4 | PASSKEY = 'pky', 5 | PASSWORD = 'pwd', 6 | WEB3 = 'wb3', 7 | } 8 | 9 | export enum PrimaryAuthMethod { 10 | AUTH_ZERO = 'AUTH_ZERO', 11 | MAGIC_LINK = 'MAGIC_LINK', 12 | MICROSOFT_ENTRA = 'MICROSOFT_ENTRA', 13 | OKTA = 'OKTA', 14 | PASSWORD = 'PASSWORD', 15 | } 16 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/src/utils/urls.ts: -------------------------------------------------------------------------------- 1 | export const formatRedirectUrl = (url: string): string => { 2 | const parsedUrl = new URL(url); 3 | const currentLocation = window.location; 4 | 5 | if (parsedUrl.hostname === currentLocation.hostname) { 6 | if (parsedUrl.pathname === currentLocation.pathname) { 7 | // If the pathname is the same, then the redirect is to the same page, so we should just return the root path 8 | return '/'; 9 | } 10 | return parsedUrl.pathname + parsedUrl.search; 11 | } 12 | return url; 13 | }; 14 | -------------------------------------------------------------------------------- /src/packages/auth-ui-components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "ESNext", 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "module": "ESNext", 7 | "jsx": "react-jsx", 8 | "outDir": "./lib", 9 | "rootDir": "./src", 10 | "types": ["vite/client"] 11 | }, 12 | "include": ["./src", "./@types"], 13 | "references": [{ "path": "../admin-ui-components" }] 14 | } 15 | -------------------------------------------------------------------------------- /src/packages/auth/README.md: -------------------------------------------------------------------------------- 1 | # `@exogee/graphweaver-auth` 2 | 3 | A security wrapper provider for @exogee/graphweaver 4 | 5 | ## Documentation 6 | 7 | Comprehensive documentation and usage examples can be found on our [Docs Site](https://graphweaver.com/docs). It covers installation instructions, detailed API documentation, and guides to help you get started with Graphweaver. 8 | 9 | ## Graphweaver CLI `graphweaver` 10 | 11 | The Graphweaver Command Line Interface (CLI) tool enables you to set up and manage Graphweaver using commands in your command-line shell. Check the `graphweaver` npm package [here.](https://www.npmjs.com/package/graphweaver) 12 | -------------------------------------------------------------------------------- /src/packages/auth/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | 5 | const entryPoints = await glob('./src/**/*.ts', { ignore: './src/**/*.test.ts' }); 6 | await esbuild.build({ 7 | outdir: 'lib', 8 | format: 'cjs', 9 | platform: 'node', 10 | sourcemap: 'linked', 11 | entryPoints, 12 | }); 13 | })(); 14 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/apollo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './plugin'; 2 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/entities/authentication.ts: -------------------------------------------------------------------------------- 1 | export interface AuthenticationBaseEntity { 2 | id: string; 3 | type: string; 4 | userId: string; 5 | data: T; 6 | createdAt: Date; 7 | } 8 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './authentication'; 2 | export * from './token'; 3 | export * from './credential'; 4 | export * from './api-key'; 5 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/entities/token.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field } from '@exogee/graphweaver'; 2 | 3 | export class AuthToken { 4 | constructor(public readonly authToken: string) { 5 | this.authToken = authToken; 6 | } 7 | } 8 | 9 | @Entity('Token', { 10 | apiOptions: { 11 | excludeFromBuiltInOperations: true, 12 | }, 13 | }) 14 | export class Token { 15 | @Field(() => String, { primaryKeyField: true }) 16 | authToken!: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/index.ts: -------------------------------------------------------------------------------- 1 | export * from './token'; 2 | export * from './methods'; 3 | export * from './apollo'; 4 | export * from './entities'; 5 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/methods/auth-zero.ts: -------------------------------------------------------------------------------- 1 | import { BaseAuthMethod } from './base-auth-method'; 2 | 3 | export class AuthZero extends BaseAuthMethod {} 4 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/methods/index.ts: -------------------------------------------------------------------------------- 1 | export * from './api-key'; 2 | export * from './auth-zero'; 3 | export * from './forgotten-password'; 4 | export * from './magic-link'; 5 | export * from './microsoft-entra'; 6 | export * from './okta'; 7 | export * from './one-time-password'; 8 | export * from './passkey'; 9 | export * from './password'; 10 | export * from './web3'; 11 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/methods/microsoft-entra.ts: -------------------------------------------------------------------------------- 1 | import { BaseAuthMethod } from './base-auth-method'; 2 | 3 | export class MicrosoftEntra extends BaseAuthMethod {} 4 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/methods/okta.ts: -------------------------------------------------------------------------------- 1 | import { BaseAuthMethod } from './base-auth-method'; 2 | 3 | export class Okta extends BaseAuthMethod {} 4 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/token/base-auth-token-provider.ts: -------------------------------------------------------------------------------- 1 | import { JwtPayload } from 'jsonwebtoken'; 2 | import { AuthToken } from '../entities'; 3 | import { UserProfile } from '../../user-profile'; 4 | 5 | export interface BaseAuthTokenProvider { 6 | generateToken: (user: UserProfile) => Promise; 7 | decodeToken: (authToken: string) => Promise; 8 | stepUpToken: (existingTokenPayload: JwtPayload) => Promise; 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/auth/src/authentication/token/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auth-token'; 2 | -------------------------------------------------------------------------------- /src/packages/auth/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './apply-access-control-list'; 2 | export * from './apply-multi-factor-authentication'; 3 | -------------------------------------------------------------------------------- /src/packages/auth/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './authentication'; 2 | export * from './decorators'; 3 | export * from './errors'; 4 | export * from './helper-functions'; 5 | export * from './implicit-authorization'; 6 | export * from './types'; 7 | export * from './user-context'; 8 | export * from './user-profile'; 9 | export * from './utils/argon2id'; 10 | -------------------------------------------------------------------------------- /src/packages/auth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "rootDir": "./src", 6 | "noUnusedLocals": false 7 | }, 8 | "include": ["./src", "../../@types"], 9 | "exclude": ["src/**/*.test.ts"], 10 | "references": [ 11 | { "path": "../core" }, 12 | { "path": "../logger" }, 13 | { "path": "../scalars" }, 14 | { "path": "../server" } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/packages/auth/vite.config.ts: -------------------------------------------------------------------------------- 1 | // vite.config.ts 2 | import { defineConfig } from 'vitest/config'; 3 | 4 | export default defineConfig({ 5 | test: { 6 | globals: true, 7 | include: ['./src/**/*.test.ts'], 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /src/packages/aws-cognito/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | pnpm-lock.yaml 4 | -------------------------------------------------------------------------------- /src/packages/aws-cognito/README.md: -------------------------------------------------------------------------------- 1 | # graphweaver-AWS 2 | 3 | This provides an integration to AWS's cognito service to create and get users. 4 | -------------------------------------------------------------------------------- /src/packages/aws-cognito/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | await esbuild.build({ 4 | outdir: 'lib', 5 | format: 'cjs', 6 | platform: 'node', 7 | sourcemap: 'linked', 8 | entryPoints: ['src/index.ts'], 9 | bundle: true, 10 | external: ['@exogee/graphweaver', 'type-graphql', 'graphql-type-json'], 11 | }); 12 | })(); 13 | -------------------------------------------------------------------------------- /src/packages/aws-cognito/src/entities/backend-entity.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Field } from '@exogee/graphweaver-rest-legacy'; 2 | 3 | export class CognitoUserBackendEntity extends BaseEntity { 4 | @Field() 5 | id!: string; 6 | 7 | @Field() 8 | username!: string; 9 | 10 | @Field() 11 | enabled!: boolean; 12 | 13 | @Field() 14 | email!: string; 15 | 16 | @Field() 17 | userStatus!: string; 18 | 19 | @Field() 20 | groups!: string[]; 21 | 22 | @Field() 23 | attributes!: string; 24 | } 25 | -------------------------------------------------------------------------------- /src/packages/aws-cognito/src/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './backend-entity'; 2 | export * from './graphql-entity'; 3 | -------------------------------------------------------------------------------- /src/packages/aws-cognito/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './entities'; 2 | export * from './provider'; 3 | -------------------------------------------------------------------------------- /src/packages/aws-cognito/src/provider/index.ts: -------------------------------------------------------------------------------- 1 | export * from './base-provider'; 2 | export * from './user-provider'; 3 | -------------------------------------------------------------------------------- /src/packages/aws-cognito/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "rootDir": "./src", 6 | "noUnusedLocals": false, 7 | "experimentalDecorators": true, 8 | "target": "es2019", 9 | "module": "CommonJS", 10 | "allowSyntheticDefaultImports": true, 11 | "esModuleInterop": true, 12 | "jsx": "react-jsx" 13 | }, 14 | "include": ["./src"], 15 | "references": [{ "path": "../core" }, { "path": "../rest-legacy" }] 16 | } 17 | -------------------------------------------------------------------------------- /src/packages/builder/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | !bin 3 | bin/index.js 4 | node_modules 5 | *.log 6 | -------------------------------------------------------------------------------- /src/packages/builder/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | bin 4 | -------------------------------------------------------------------------------- /src/packages/builder/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | 5 | const entryPoints = await glob('./src/**/*.ts'); 6 | await esbuild.build({ 7 | outdir: 'lib', 8 | format: 'cjs', 9 | platform: 'node', 10 | sourcemap: 'linked', 11 | entryPoints, 12 | }); 13 | })(); 14 | -------------------------------------------------------------------------------- /src/packages/builder/src/auth/config.ts: -------------------------------------------------------------------------------- 1 | export const generateConfig = async (method: 'password' | 'magic-link') => { 2 | return ` 3 | // Generated Graphweaver Config 4 | // This file contains the Graphweaver configuration used by the auth system. 5 | module.exports = { 6 | adminUI: { 7 | auth: { 8 | primaryMethods: ["${method === 'password' ? 'PASSWORD' : 'MAGIC_LINK'}"], 9 | }, 10 | }, 11 | }; 12 | `; 13 | }; 14 | -------------------------------------------------------------------------------- /src/packages/builder/src/build/index.ts: -------------------------------------------------------------------------------- 1 | export * from './backend'; 2 | export * from './frontend'; 3 | -------------------------------------------------------------------------------- /src/packages/builder/src/bundle/index.ts: -------------------------------------------------------------------------------- 1 | export * from './analyse'; 2 | -------------------------------------------------------------------------------- /src/packages/builder/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auth'; 2 | export * from './bundle'; 3 | export * from './build'; 4 | export * from './introspection'; 5 | export * from './start'; 6 | export * from './codegen'; 7 | -------------------------------------------------------------------------------- /src/packages/builder/src/introspection/index.ts: -------------------------------------------------------------------------------- 1 | import { introspection } from '@exogee/graphweaver-mikroorm'; 2 | 3 | import { DatabaseOptions } from '../auth'; 4 | 5 | export const startIntrospection = async (databaseOptions: DatabaseOptions) => { 6 | if (!databaseOptions.source) { 7 | throw new Error('No source specified, please specify a data source.'); 8 | } 9 | 10 | return introspection(databaseOptions.source, { 11 | mikroOrmConfig: { 12 | host: databaseOptions.host, 13 | dbName: databaseOptions.dbName, 14 | user: databaseOptions.user, 15 | password: databaseOptions.password, 16 | port: databaseOptions.port, 17 | }, 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /src/packages/builder/src/start/index.ts: -------------------------------------------------------------------------------- 1 | export * from './backend'; 2 | export * from './frontend'; 3 | -------------------------------------------------------------------------------- /src/packages/builder/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "rootDir": "./src", 6 | "outDir": "./lib" 7 | }, 8 | "references": [ 9 | { "path": "../admin-ui" }, 10 | { "path": "../config" }, 11 | { "path": "../mikroorm" }, 12 | { "path": "../vite-plugin-graphweaver" } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/packages/builder/vite.config.ts: -------------------------------------------------------------------------------- 1 | // vite.config.ts 2 | import { defineConfig } from 'vitest/config'; 3 | 4 | export default defineConfig({ 5 | test: { 6 | globals: true, 7 | include: ['./src/**/*.test.ts'], 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /src/packages/cdk/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ignorePatterns: ['.deploy/**', '.build/**', 'lib/**'], 3 | }; 4 | -------------------------------------------------------------------------------- /src/packages/cdk/.gitignore: -------------------------------------------------------------------------------- 1 | cdk.out 2 | cdk.context.json -------------------------------------------------------------------------------- /src/packages/cdk/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | 5 | // Get all entry points for the build but not the test files 6 | const entryPoints = await glob('./src/**/*.ts', { 7 | ignore: ['./src/**/*.test.ts'], 8 | }); 9 | await esbuild.build({ 10 | outdir: 'lib', 11 | format: 'cjs', 12 | platform: 'node', 13 | sourcemap: 'linked', 14 | entryPoints, 15 | }); 16 | })(); 17 | -------------------------------------------------------------------------------- /src/packages/cdk/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "esrun src/examples/ecs.ts", 3 | "requireApproval": "never" 4 | } 5 | -------------------------------------------------------------------------------- /src/packages/cdk/src/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the official Node.js image as the base 2 | FROM node:22 3 | 4 | # Set the working directory within the container 5 | WORKDIR /usr/src/app 6 | 7 | # Copy the application code from the specified directory 8 | COPY ./ ./ 9 | 10 | # Expose the port your app will run on (e.g., 9001) 11 | EXPOSE 9001 12 | 13 | # Run the application (replace with your actual command) 14 | CMD ["node", "index.js"] -------------------------------------------------------------------------------- /src/packages/cdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "rootDir": "./src", 6 | "outDir": "./lib", 7 | "typeRoots": ["./node_modules/@types"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/cli/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | !bin/gw-bin.js 3 | !bin/gw-types.js 4 | !bin/gw-print-schema.js 5 | bin 6 | node_modules 7 | *.log 8 | -------------------------------------------------------------------------------- /src/packages/cli/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bin 3 | -------------------------------------------------------------------------------- /src/packages/cli/bin/gw-bin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* eslint-disable @typescript-eslint/no-require-imports */ 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | 6 | if (fs.existsSync(path.join(__dirname, 'index.js'))) { 7 | require('./index.js'); 8 | } else { 9 | console.log('You need to build the cli package first'); 10 | } 11 | -------------------------------------------------------------------------------- /src/packages/cli/test-init.js: -------------------------------------------------------------------------------- 1 | const { initGraphWeaver } = require('./bin'); 2 | initGraphWeaver('test', [0], 'workspace:*'); 3 | -------------------------------------------------------------------------------- /src/packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src", "./package.json"], 4 | "compilerOptions": { 5 | "rootDir": ".", 6 | "outDir": "./lib", 7 | "resolveJsonModule": true 8 | }, 9 | "references": [ 10 | { "path": "../config" }, 11 | { "path": "../builder" }, 12 | { "path": "../mikroorm" }, 13 | { "path": "../vite-plugin-graphweaver" } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/packages/config/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | !bin 3 | bin/index.js 4 | node_modules 5 | *.log 6 | -------------------------------------------------------------------------------- /src/packages/config/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | bin 4 | -------------------------------------------------------------------------------- /src/packages/config/README.md: -------------------------------------------------------------------------------- 1 | # Graphweaver Config `@exogee/graphweaver-config` 2 | 3 | Retrieve and parse Graphweaver configuration. 4 | 5 | ## Documentation 6 | 7 | Comprehensive documentation and usage examples can be found on our [Docs Site](https://graphweaver.com/docs). It covers installation instructions, detailed API documentation, and guides to help you get started with Graphweaver. 8 | 9 | ## Graphweaver CLI `graphweaver` 10 | 11 | The Graphweaver Command Line Interface (CLI) tool enables you to set up and manage Graphweaver using commands in your command-line shell. Check the `graphweaver` npm package [here.](https://www.npmjs.com/package/graphweaver) 12 | -------------------------------------------------------------------------------- /src/packages/config/build.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-require-imports */ 2 | const { build } = require('esbuild'); 3 | const { dependencies, devDependencies } = require('./package.json'); 4 | 5 | (async () => { 6 | await build({ 7 | entryPoints: ['./src/index.ts'], 8 | outdir: 'lib', 9 | bundle: true, 10 | platform: 'node', 11 | banner: { js: '#!/usr/bin/env node' }, 12 | external: [ 13 | // Our dependencies will be installed in node_modules. The bundling is 14 | // just to ensure our own files are pulled in 15 | ...Object.keys(dependencies), 16 | ...Object.keys(devDependencies), 17 | ], 18 | }); 19 | })(); 20 | -------------------------------------------------------------------------------- /src/packages/config/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './config'; 2 | -------------------------------------------------------------------------------- /src/packages/config/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "rootDir": "./src", 6 | "outDir": "./lib", 7 | "typeRoots": ["./node_modules/@types"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/core/README.md: -------------------------------------------------------------------------------- 1 | # `@exogee/graphweaver` 2 | 3 | Core package for Graphweaver 4 | 5 | ## Documentation 6 | 7 | Comprehensive documentation and usage examples can be found on our [Docs Site](https://graphweaver.com/docs). It covers installation instructions, detailed API documentation, and guides to help you get started with Graphweaver. 8 | 9 | ## Graphweaver CLI `graphweaver` 10 | 11 | The Graphweaver Command Line Interface (CLI) tool enables you to set up and manage Graphweaver using commands in your command-line shell. Check the `graphweaver` npm package [here.](https://www.npmjs.com/package/graphweaver) 12 | -------------------------------------------------------------------------------- /src/packages/core/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | const entryPoints = await glob('./src/**/*.ts', { ignore: '**/*.test.ts' }); 5 | await esbuild.build({ 6 | outdir: 'lib', 7 | format: 'cjs', 8 | platform: 'node', 9 | sourcemap: 'linked', 10 | entryPoints, 11 | }); 12 | })(); 13 | -------------------------------------------------------------------------------- /src/packages/core/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './entity'; 2 | export * from './input-type'; 3 | export * from './field'; 4 | export * from './hook'; 5 | export * from './provider'; 6 | export * from './relationship-field'; 7 | -------------------------------------------------------------------------------- /src/packages/core/src/decorators/provider.ts: -------------------------------------------------------------------------------- 1 | import { graphweaverMetadata } from '../metadata'; 2 | import { BackendProvider } from '../types'; 3 | 4 | export function Provider(provider: BackendProvider) { 5 | return (target: { new (...args: any[]): G }) => { 6 | graphweaverMetadata.collectProviderInformationForEntity({ 7 | provider, 8 | target, 9 | }); 10 | 11 | return target; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /src/packages/core/src/federation/enums.ts: -------------------------------------------------------------------------------- 1 | import { graphweaverMetadata } from '../metadata'; 2 | 3 | export enum LinkPurpose { 4 | SECURITY = 'SECURITY', 5 | EXECUTION = 'EXECUTION', 6 | } 7 | 8 | export const addEnums = () => { 9 | graphweaverMetadata.collectEnumInformation({ 10 | name: 'link__Purpose', 11 | target: LinkPurpose, 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /src/packages/core/src/federation/scalars.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLScalarType } from 'graphql'; 2 | 3 | export const AnyGraphQLType = new GraphQLScalarType({ 4 | name: '_Any', 5 | serialize(value) { 6 | return value; 7 | }, 8 | }); 9 | 10 | export const LinkImportGraphQLType = new GraphQLScalarType({ 11 | name: 'link__Import', 12 | specifiedByURL: null, 13 | }); 14 | 15 | export const FieldSetGraphQLType = new GraphQLScalarType({ 16 | name: 'federation__FieldSet', 17 | }); 18 | -------------------------------------------------------------------------------- /src/packages/core/src/metadata-service/entity-attribute.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field } from '../decorators'; 2 | 3 | @Entity('AdminUiEntityAttributeMetadata', { 4 | apiOptions: { excludeFromBuiltInOperations: true, excludeFromFederation: true }, 5 | }) 6 | export class AdminUiEntityAttributeMetadata { 7 | @Field(() => Boolean, { nullable: true }) 8 | isReadOnly?: boolean; 9 | 10 | @Field(() => Number, { nullable: true }) 11 | exportPageSize?: number; 12 | 13 | @Field(() => Boolean, { nullable: true }) 14 | clientGeneratedPrimaryKeys?: boolean; 15 | } 16 | -------------------------------------------------------------------------------- /src/packages/core/src/metadata-service/enum-value.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field } from '../decorators'; 2 | 3 | @Entity('AdminUiEnumValueMetadata', { 4 | apiOptions: { excludeFromBuiltInOperations: true, excludeFromFederation: true }, 5 | }) 6 | export class AdminUiEnumValueMetadata { 7 | @Field(() => String) 8 | name!: string; 9 | 10 | @Field(() => String) 11 | value!: string; 12 | } 13 | -------------------------------------------------------------------------------- /src/packages/core/src/metadata-service/enum.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field } from '../decorators'; 2 | import { AdminUiEnumValueMetadata } from './enum-value'; 3 | 4 | @Entity('AdminUiEnumMetadata', { 5 | apiOptions: { excludeFromBuiltInOperations: true, excludeFromFederation: true }, 6 | }) 7 | export class AdminUiEnumMetadata { 8 | @Field(() => String) 9 | name!: string; 10 | 11 | @Field(() => [AdminUiEnumValueMetadata]) 12 | values() { 13 | return []; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/packages/core/src/metadata-service/field-attribute.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field } from '../decorators'; 2 | 3 | @Entity('AdminUiFieldAttributeMetadata', { 4 | apiOptions: { excludeFromBuiltInOperations: true, excludeFromFederation: true }, 5 | }) 6 | export class AdminUiFieldAttributeMetadata { 7 | @Field(() => Boolean) 8 | isReadOnly!: boolean; 9 | 10 | @Field(() => Boolean) 11 | isRequired!: boolean; 12 | } 13 | -------------------------------------------------------------------------------- /src/packages/core/src/metadata-service/field-extensions.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field } from '../decorators'; 2 | 3 | @Entity('AdminUiFieldExtensionsMetadata', { 4 | apiOptions: { excludeFromBuiltInOperations: true, excludeFromFederation: true }, 5 | }) 6 | export class AdminUiFieldExtensionsMetadata { 7 | @Field(() => String, { nullable: true }) 8 | key?: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/core/src/metadata-service/field-format.ts: -------------------------------------------------------------------------------- 1 | import { DateTimeFormat, Entity, Field } from '../decorators'; 2 | 3 | @Entity('AdminUiFieldFormatMetadata', { 4 | apiOptions: { excludeFromBuiltInOperations: true, excludeFromFederation: true }, 5 | }) 6 | export class AdminUiFieldFormatMetadata { 7 | @Field(() => String, { nullable: false }) 8 | type!: 'date' | 'currency'; 9 | 10 | @Field(() => String, { nullable: true }) 11 | timezone?: string; 12 | 13 | @Field(() => String, { nullable: true }) 14 | format?: DateTimeFormat; 15 | 16 | @Field(() => String, { nullable: true }) 17 | variant?: string; 18 | } 19 | -------------------------------------------------------------------------------- /src/packages/core/src/metadata-service/index.ts: -------------------------------------------------------------------------------- 1 | export * from './entity-attribute'; 2 | export * from './entity'; 3 | export * from './enum-value'; 4 | export * from './enum'; 5 | export * from './field-attribute'; 6 | export * from './field-extensions'; 7 | export * from './field'; 8 | export * from './filter'; 9 | export * from './metadata'; 10 | export * from './resolver'; 11 | -------------------------------------------------------------------------------- /src/packages/core/src/metadata-service/metadata.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Field } from '../decorators'; 2 | import { AdminUiEntityMetadata } from './entity'; 3 | import { AdminUiEnumMetadata } from './enum'; 4 | 5 | @Entity('AdminUiMetadata', { 6 | apiOptions: { excludeFromBuiltInOperations: true, excludeFromFederation: true }, 7 | }) 8 | export class AdminUiMetadata { 9 | @Field(() => [AdminUiEntityMetadata]) 10 | public entities: AdminUiEntityMetadata[] = []; 11 | 12 | @Field(() => [AdminUiEnumMetadata]) 13 | public enums: AdminUiEnumMetadata[] = []; 14 | } 15 | -------------------------------------------------------------------------------- /src/packages/core/src/open-telemetry/index.ts: -------------------------------------------------------------------------------- 1 | export * from './tracing'; 2 | export * from './exporter'; 3 | export * from './entity'; 4 | -------------------------------------------------------------------------------- /src/packages/core/src/operations.ts: -------------------------------------------------------------------------------- 1 | export const arrayOperations = new Set(['in', 'nin']); 2 | export const basicOperations = new Set(['ne', 'notnull', 'null']); 3 | export const likeOperations = new Set(['like', 'ilike']); 4 | export const mathOperations = new Set(['gt', 'gte', 'lt', 'lte']); 5 | export const allOperations = new Set([ 6 | ...arrayOperations, 7 | ...basicOperations, 8 | ...likeOperations, 9 | ...mathOperations, 10 | ]); 11 | -------------------------------------------------------------------------------- /src/packages/core/src/utils/common.ts: -------------------------------------------------------------------------------- 1 | export const isDefined = (value: T | undefined | null): value is T => 2 | value !== undefined && value !== null; 3 | -------------------------------------------------------------------------------- /src/packages/core/src/utils/has-id.ts: -------------------------------------------------------------------------------- 1 | import { EntityMetadata, graphweaverMetadata } from '../metadata'; 2 | 3 | export const hasId = ( 4 | entityMetdata: EntityMetadata, 5 | value: Partial 6 | ) => { 7 | const primaryKeyField = graphweaverMetadata.primaryKeyFieldForEntity(entityMetdata); 8 | const typeOfPrimaryKeyValue = typeof value[primaryKeyField as keyof G]; 9 | 10 | return typeOfPrimaryKeyValue === 'string' || typeOfPrimaryKeyValue === 'number'; 11 | }; 12 | -------------------------------------------------------------------------------- /src/packages/core/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './apply-default-values'; 2 | export * from './has-id'; 3 | export * from './plural'; 4 | export * from './with-transaction'; 5 | export * from './common'; 6 | -------------------------------------------------------------------------------- /src/packages/core/src/utils/plural.ts: -------------------------------------------------------------------------------- 1 | import pluralize from 'pluralize'; 2 | 3 | const formatString = (str: string): string => `${str.charAt(0).toUpperCase()}${str.substring(1)}`; 4 | 5 | export const pluralise = (str: string, userOverride: boolean): string => { 6 | if (userOverride) { 7 | return formatString(str); 8 | } 9 | const plural = pluralize.plural(str); 10 | return plural === str ? `Multiple${formatString(str)}` : formatString(plural); 11 | }; 12 | -------------------------------------------------------------------------------- /src/packages/core/src/utils/with-transaction.ts: -------------------------------------------------------------------------------- 1 | import { BackendProvider } from '../types'; 2 | 3 | export const withTransaction = async ( 4 | provider: BackendProvider, 5 | callback: () => Promise 6 | ) => { 7 | return provider.withTransaction ? provider.withTransaction(callback) : callback(); 8 | }; 9 | -------------------------------------------------------------------------------- /src/packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "rootDir": "./src", 6 | "outDir": "./lib", 7 | "resolveJsonModule": true 8 | }, 9 | "references": [{ "path": "../logger" }, { "path": "../scalars" }] 10 | } 11 | -------------------------------------------------------------------------------- /src/packages/end-to-end/.env.rest.example: -------------------------------------------------------------------------------- 1 | AUTH_BASE_URI="http://localhost:9000" 2 | AUTH_WHITELIST_DOMAINS="localhost" 3 | AUTH_MAGIC_LINK_RATE_LIMIT="500" 4 | AUTH_JWT_CHALLENGE_EXPIRES_IN="30m"; 5 | AUTH_PUBLIC_KEY_PEM_BASE64='LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFcVFSUC9nem1ZdVJyR012UzJxeXpLaU05c0Z2aQpyWFRWVUsrMDBHaFFDa2NhdThOcWZsWG9nOEhyTkVsalkwWWpYcVVqOCs2ZDlySkEwTHo0NmFGSmp3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=='; 6 | AUTH_PRIVATE_KEY_PEM_BASE64= 7 | -------------------------------------------------------------------------------- /src/packages/end-to-end/.env.sqlite: -------------------------------------------------------------------------------- 1 | DATABASE=sqlite -------------------------------------------------------------------------------- /src/packages/end-to-end/.gitignore: -------------------------------------------------------------------------------- 1 | app 2 | node_modules 3 | *.log 4 | 5 | # Playwright Files 6 | /test-results/ 7 | /playwright-report/ 8 | /playwright/.cache/ 9 | 10 | local_modules -------------------------------------------------------------------------------- /src/packages/end-to-end/databases/database.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/packages/end-to-end/databases/database.sqlite -------------------------------------------------------------------------------- /src/packages/end-to-end/databases/postgres.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/packages/end-to-end/databases/postgres.sql -------------------------------------------------------------------------------- /src/packages/end-to-end/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest').JestConfigWithTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | setupFiles: ['./jest.setup.js'], 6 | }; 7 | -------------------------------------------------------------------------------- /src/packages/end-to-end/jest.setup.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-require-imports */ 2 | // set up environment variables for jest 3 | const dotenv = require('dotenv'); 4 | dotenv.config({ 5 | path: '.env', 6 | }); 7 | -------------------------------------------------------------------------------- /src/packages/end-to-end/scripts/import-postgres.sh: -------------------------------------------------------------------------------- 1 | rm -rf ./app 2 | node ./local_modules/graphweaver/bin init --name=app --backend=postgres --useVersion=\"local\" 3 | cd app 4 | pnpm i --ignore-workspace --no-lockfile 5 | pnpm run import postgresql --database=gw --user=postgres --password=postgres --host=localhost --port=5432 --o 6 | pnpm build -------------------------------------------------------------------------------- /src/packages/end-to-end/src/__tests__/api/storage-provider/fixtures/pickle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/packages/end-to-end/src/__tests__/api/storage-provider/fixtures/pickle.png -------------------------------------------------------------------------------- /src/packages/end-to-end/src/__tests__/api/storage-provider/fixtures/tomato-chair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/packages/end-to-end/src/__tests__/api/storage-provider/fixtures/tomato-chair.png -------------------------------------------------------------------------------- /src/packages/end-to-end/src/__tests__/fuzzer/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './fuzzer'; 2 | export * from './static'; -------------------------------------------------------------------------------- /src/packages/end-to-end/src/__tests__/fuzzer/utils/static.ts: -------------------------------------------------------------------------------- 1 | import { request } from "."; 2 | 3 | // Taken from https://github.com/swisskyrepo/GraphQLmap 4 | export const CHARSET = '!$%\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~'; 5 | 6 | export const loginRequest = request` 7 | mutation loginPassword($username: String, $password: String) { 8 | loginPassword(username: $username, password: $password) { 9 | authToken 10 | } 11 | } 12 | `; -------------------------------------------------------------------------------- /src/packages/end-to-end/src/__tests__/ui/auth/README.md: -------------------------------------------------------------------------------- 1 | # Auth Tests 2 | 3 | The UI tests in this folder use the `./examples/rest-with-auth` app as their test site. 4 | -------------------------------------------------------------------------------- /src/packages/end-to-end/src/__tests__/ui/sqlite/components/404-pages.test.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | import { config } from '../../../../config'; 3 | 4 | test('404 Page - should show when accessing a genuine 404', async ({ page }) => { 5 | await page.goto(`${config.adminUiUrl}/non-existent-page/that/is/really/nested`); 6 | await expect(page.getByText('404 - Unknown Page')).toBeVisible(); 7 | }); 8 | 9 | test('Unknown Entity Page - should show when accessing an unknown URL', async ({ page }) => { 10 | await page.goto(`${config.adminUiUrl}/non-existent-page`); 11 | await expect(page.getByText('No such entity: non-existent-page')).toBeVisible(); 12 | }); 13 | -------------------------------------------------------------------------------- /src/packages/end-to-end/src/__tests__/ui/sqlite/components/list-page.test.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | import { config } from '../../../../config'; 3 | 4 | test('List Page', async ({ page }) => { 5 | await page.goto(config.adminUiUrl); 6 | await page.getByRole('link', { name: 'Artist' }).click(); 7 | 8 | await expect(page.getByText('From mikro-orm-sqlite (275 rows)')).toBeVisible(); 9 | await expect(page.getByRole('cell', { name: 'Plays Metallica By Four Cellos' })).toBeVisible(); 10 | }); 11 | -------------------------------------------------------------------------------- /src/packages/end-to-end/src/__tests__/ui/sqlite/components/sidebar.test.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test'; 2 | import { config } from '../../../../config'; 3 | 4 | test('Expand datasource dropdown', async ({ page }) => { 5 | await page.goto(config.adminUiUrl); 6 | await page.getByRole('link', { name: 'Album' }).click(); 7 | 8 | await expect(page.getByRole('heading', { name: 'Album' })).toBeVisible(); 9 | }); 10 | -------------------------------------------------------------------------------- /src/packages/end-to-end/src/__tests__/ui/storage-provider/fixtures/pickle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/packages/end-to-end/src/__tests__/ui/storage-provider/fixtures/pickle.png -------------------------------------------------------------------------------- /src/packages/end-to-end/src/__tests__/ui/storage-provider/fixtures/tomato-chair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/packages/end-to-end/src/__tests__/ui/storage-provider/fixtures/tomato-chair.png -------------------------------------------------------------------------------- /src/packages/end-to-end/src/config.ts: -------------------------------------------------------------------------------- 1 | export const config = { 2 | baseUrl: process.env.TEST_BASE_URL || 'http://localhost:9001', 3 | adminUiUrl: process.env.TEST_ADMIN_UI_URL || 'http://localhost:9000', 4 | appDirectory: process.env.TEST_APP_DIRECTORY || './app', 5 | datasource: process.env.TEST_DATASOURCE || 'mikro-orm-sqlite', 6 | }; 7 | -------------------------------------------------------------------------------- /src/packages/end-to-end/src/utils.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { config } from './config'; 4 | 5 | const database = process.env.DATABASE; 6 | 7 | export enum Database { 8 | SQLITE = 'sqlite', 9 | POSTGRES = 'postgres', 10 | MYSQL = 'mysql', 11 | } 12 | 13 | export const resetDatabase = async () => { 14 | if (!database) { 15 | throw new Error('Please specify a database to use'); 16 | } 17 | if (database === Database.SQLITE) { 18 | fs.copyFileSync( 19 | path.join(process.cwd(), 'databases', 'database.sqlite'), 20 | path.join(process.cwd(), config.appDirectory, 'databases', 'database.sqlite') 21 | ); 22 | return; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/packages/load-testing/.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | !bin 3 | bin/index.js 4 | node_modules 5 | *.log 6 | -------------------------------------------------------------------------------- /src/packages/load-testing/bin/k6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exogee-technology/graphweaver/16bb0d40703a635fccdbd20f840a5c731fccd92e/src/packages/load-testing/bin/k6 -------------------------------------------------------------------------------- /src/packages/load-testing/src/config.ts: -------------------------------------------------------------------------------- 1 | export const url = 'http://localhost:9001/'; 2 | -------------------------------------------------------------------------------- /src/packages/load-testing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "rootDir": "./src", 6 | "outDir": "./lib", 7 | "typeRoots": ["./node_modules/@types"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/logger/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ignorePatterns: ['.deploy/**', '.build/**', 'lib/**'], 3 | }; 4 | -------------------------------------------------------------------------------- /src/packages/logger/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | 5 | const entryPoints = await glob('./src/**/*.ts'); 6 | 7 | await esbuild.build({ 8 | outdir: 'lib', 9 | format: 'cjs', 10 | platform: 'node', 11 | sourcemap: 'linked', 12 | entryPoints, 13 | }); 14 | })(); 15 | -------------------------------------------------------------------------------- /src/packages/logger/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './logger'; 2 | -------------------------------------------------------------------------------- /src/packages/logger/src/logger.ts: -------------------------------------------------------------------------------- 1 | import pino from 'pino'; 2 | 3 | const validLevels = { 4 | warn: true, 5 | trace: true, 6 | debug: true, 7 | info: true, 8 | error: true, 9 | fatal: true, 10 | }; 11 | 12 | type LoggingLevel = keyof typeof validLevels; 13 | const level: LoggingLevel = (process.env.LOGGING_LEVEL as LoggingLevel) || 'info'; 14 | 15 | if (!validLevels[level]) 16 | throw new Error( 17 | `Invalid logging level ${level}, valid levels are ${Object.keys(validLevels).join(', ')}` 18 | ); 19 | 20 | export const logger = pino({ 21 | name: 'graphweaver', 22 | level, 23 | }); 24 | -------------------------------------------------------------------------------- /src/packages/logger/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./lib" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /src/packages/mikro-orm-sqlite-wasm/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | 5 | const entryPoints = await glob('./src/**/*.ts'); 6 | await esbuild.build({ 7 | outdir: 'lib', 8 | format: 'cjs', 9 | platform: 'node', 10 | sourcemap: 'linked', 11 | entryPoints, 12 | }); 13 | })(); 14 | -------------------------------------------------------------------------------- /src/packages/mikro-orm-sqlite-wasm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./lib" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /src/packages/mikroorm/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ignorePatterns: ['.deploy/**', '.build/**', 'lib/**'], 3 | }; 4 | -------------------------------------------------------------------------------- /src/packages/mikroorm/scripts/test-introspection.ts: -------------------------------------------------------------------------------- 1 | import { introspection } from '../src'; 2 | 3 | const go = async () => { 4 | await introspection('postgresql', { 5 | mikroOrmConfig: { 6 | host: 'localhost', 7 | port: 5432, 8 | dbName: 'introspection_test', 9 | }, 10 | }); 11 | }; 12 | 13 | go(); 14 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/config.ts: -------------------------------------------------------------------------------- 1 | import { logger } from '@exogee/logger'; 2 | 3 | export const requireEnvironmentVariable = ( 4 | envStr: string, 5 | warnOnly?: boolean 6 | ): string | undefined => { 7 | const envVar = process.env[envStr]; 8 | if (!envVar) { 9 | if (warnOnly) { 10 | logger.warn(`${envStr} is required in environment.`); 11 | return; 12 | } 13 | throw new Error(`${envStr} required but not found.`); 14 | } 15 | return envVar; 16 | }; 17 | 18 | export const config = {}; 19 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './external-id-field'; 2 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/entities/audit-related-entity-change.ts: -------------------------------------------------------------------------------- 1 | import { BigIntType, Entity, Ref, Index, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'; 2 | 3 | import { AuditChange } from './audit-change'; 4 | @Entity() 5 | @Index({ properties: ['relatedEntityType', 'relatedEntityId'] }) 6 | export class AuditRelatedEntityChange { 7 | @PrimaryKey({ type: new BigIntType('string') }) 8 | id!: string; 9 | 10 | @ManyToOne(() => AuditChange, { deleteRule: 'cascade', ref: true }) 11 | change!: Ref; 12 | 13 | @Property({ type: 'string' }) 14 | relatedEntityType!: string; 15 | 16 | @Property({ type: 'string' }) 17 | relatedEntityId!: string; 18 | } 19 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './audit-change'; 2 | export * from './audit-related-entity-change'; 3 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/introspection/files/base-file.ts: -------------------------------------------------------------------------------- 1 | import { EntityMetadata, NamingStrategy, Platform } from '@mikro-orm/core'; 2 | 3 | export class BaseFile { 4 | constructor( 5 | protected readonly meta: EntityMetadata, 6 | protected readonly namingStrategy: NamingStrategy, 7 | protected readonly platform: Platform 8 | ) {} 9 | 10 | protected quote(val: string) { 11 | return val.startsWith(`'`) ? `\`${val}\`` : `'${val}'`; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/introspection/files/data-source-index-file.ts: -------------------------------------------------------------------------------- 1 | import { DatabaseType } from '../../database'; 2 | 3 | export class DataSourceIndexFile { 4 | constructor(protected readonly databaseType: DatabaseType) {} 5 | 6 | getBasePath() { 7 | return `backend/entities/`; 8 | } 9 | 10 | getBaseName() { 11 | return 'index.ts'; 12 | } 13 | 14 | generate(): string { 15 | const imports = [`export * from './${this.databaseType}';`]; 16 | 17 | return `${imports.join('\n')}\n`; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/introspection/files/index.ts: -------------------------------------------------------------------------------- 1 | export * from './data-entity-file'; 2 | export * from './data-entity-index-file'; 3 | export * from './data-source-index-file'; 4 | export * from './schema-entity-file'; 5 | export * from './schema-index-file'; 6 | export * from './database-file'; 7 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/introspection/files/schema-index-file.ts: -------------------------------------------------------------------------------- 1 | import { EntityMetadata } from '@mikro-orm/core'; 2 | 3 | export class SchemaIndexFile { 4 | constructor(protected readonly metadata: EntityMetadata[]) {} 5 | 6 | getBasePath() { 7 | return `backend/schema`; 8 | } 9 | 10 | getBaseName() { 11 | return 'index.ts'; 12 | } 13 | 14 | generate(): string { 15 | return ( 16 | this.metadata 17 | .filter((meta) => !meta.pivotTable) 18 | .map( 19 | (meta) => 20 | `import './${meta.className.replace(/([a-z0–9])([A-Z])/g, '$1-$2').toLowerCase()}';` 21 | ) 22 | .join('\n') + '\n' 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/introspection/index.ts: -------------------------------------------------------------------------------- 1 | import { ConnectionOptions, DatabaseType } from '../database'; 2 | import { generate } from './generate'; 3 | 4 | export const introspection = async (databaseType: DatabaseType, options: ConnectionOptions) => 5 | generate(databaseType, options); 6 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/plugins/index.ts: -------------------------------------------------------------------------------- 1 | export { connectToDatabase } from './connect-to-database'; 2 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/provider/index.ts: -------------------------------------------------------------------------------- 1 | export * from './provider'; 2 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './date-type'; 2 | export * from './time-type'; 3 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/utils/errors.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLError } from 'graphql'; 2 | 3 | export class OptimisticLockError extends GraphQLError { 4 | constructor(message: string, extensions: { entity: T }) { 5 | super(message, { extensions: { code: 'OPTIMISTIC_LOCK_ERROR', extensions } }); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './authentication-context'; 2 | export * from './errors'; 3 | export * from './tracked-entity'; 4 | export * from './untracked-property'; 5 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/utils/tracked-entity.ts: -------------------------------------------------------------------------------- 1 | import { BigIntType, PrimaryKey } from '@mikro-orm/core'; 2 | export abstract class TrackedEntity> { 3 | @PrimaryKey({ type: new BigIntType('string') }) 4 | id!: string; 5 | 6 | get relatedTrackedEntities(): 7 | | { 8 | id: string; 9 | entityType: string; 10 | }[] 11 | | undefined { 12 | return undefined; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/packages/mikroorm/src/utils/untracked-property.ts: -------------------------------------------------------------------------------- 1 | const untrackedPropertyMetadataKey = Symbol('UntrackedProperty'); 2 | 3 | export function UntrackedProperty() { 4 | return Reflect.metadata(untrackedPropertyMetadataKey, true); 5 | } 6 | 7 | export function isUntrackedProperty(target: any, propertyKey: string) { 8 | return Reflect.getMetadata(untrackedPropertyMetadataKey, target, propertyKey); 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/mikroorm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./lib" 6 | }, 7 | "include": ["./src"], 8 | "references": [{ "path": "../core" }, { "path": "../logger" }, { "path": "../server" }] 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/mikroorm/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | include: ['src/**/*.{test,spec}.?(c|m)[jt]s?(x)'], 6 | }, 7 | }); 8 | -------------------------------------------------------------------------------- /src/packages/rest-legacy/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | const entryPoints = await glob('./src/**/*.ts'); 5 | 6 | await esbuild.build({ 7 | outdir: 'lib', 8 | format: 'cjs', 9 | platform: 'node', 10 | sourcemap: 'linked', 11 | entryPoints, 12 | }); 13 | })(); 14 | -------------------------------------------------------------------------------- /src/packages/rest-legacy/src/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './field'; 2 | export * from './many-to-one'; 3 | export * from './many-to-many'; 4 | export * from './external-id-field'; 5 | export * from './one-to-many'; 6 | -------------------------------------------------------------------------------- /src/packages/rest-legacy/src/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './base-entity'; 2 | -------------------------------------------------------------------------------- /src/packages/rest-legacy/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './provider'; 2 | export * from './entities'; 3 | export * from './decorators'; 4 | export * from './utils'; 5 | -------------------------------------------------------------------------------- /src/packages/rest-legacy/src/provider/index.ts: -------------------------------------------------------------------------------- 1 | export * from './provider'; 2 | export * from './loader'; 3 | -------------------------------------------------------------------------------- /src/packages/rest-legacy/src/serializers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './date-serializer'; 2 | 3 | export interface Serializer { 4 | fromCrm: (value: unknown) => any; 5 | toCrm: (value: unknown) => any; 6 | } 7 | -------------------------------------------------------------------------------- /src/packages/rest-legacy/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './memory-filter'; 2 | -------------------------------------------------------------------------------- /src/packages/rest-legacy/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "rootDir": "./src", 6 | "noUnusedLocals": false 7 | }, 8 | "include": ["./src"], 9 | "references": [{ "path": "../core" }, { "path": "../logger" }] 10 | } 11 | -------------------------------------------------------------------------------- /src/packages/rest/README.md: -------------------------------------------------------------------------------- 1 | # `@exogee/graphweaver-rest` 2 | 3 | RESTful adapter package for Graphweaver. 4 | 5 | ## Documentation 6 | 7 | Comprehensive documentation and usage examples can be found on our [Docs Site](https://graphweaver.com/docs). It covers installation instructions, detailed API documentation, and guides to help you get started with Graphweaver. 8 | 9 | ## Graphweaver CLI `graphweaver` 10 | 11 | The Graphweaver Command Line Interface (CLI) tool enables you to set up and manage Graphweaver using commands in your command-line shell. Check the `graphweaver` npm package [here.](https://www.npmjs.com/package/graphweaver) 12 | -------------------------------------------------------------------------------- /src/packages/rest/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | const entryPoints = await glob('./src/**/*.ts'); 5 | 6 | await esbuild.build({ 7 | outdir: 'lib', 8 | format: 'cjs', 9 | platform: 'node', 10 | sourcemap: 'linked', 11 | entryPoints, 12 | }); 13 | })(); 14 | -------------------------------------------------------------------------------- /src/packages/rest/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './provider'; 2 | export * from './utils'; 3 | -------------------------------------------------------------------------------- /src/packages/rest/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "rootDir": "./src", 6 | "noUnusedLocals": false 7 | }, 8 | "include": ["./src"], 9 | "references": [{ "path": "../core" }, { "path": "../logger" }] 10 | } 11 | -------------------------------------------------------------------------------- /src/packages/rest/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | include: ['src/**/*.{test,spec}.?(c|m)[jt]s?(x)'], 6 | }, 7 | }); 8 | -------------------------------------------------------------------------------- /src/packages/scalars/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ignorePatterns: ['.deploy/**', '.build/**', 'lib/**'], 3 | }; 4 | -------------------------------------------------------------------------------- /src/packages/scalars/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/packages/scalars/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | 5 | const entryPoints = await glob('./src/**/*.ts'); 6 | await esbuild.build({ 7 | outdir: 'lib', 8 | format: 'cjs', 9 | platform: 'node', 10 | sourcemap: 'linked', 11 | entryPoints, 12 | }); 13 | })(); 14 | -------------------------------------------------------------------------------- /src/packages/scalars/src/index.ts: -------------------------------------------------------------------------------- 1 | export { GraphQLBigInt, GraphQLJSON, GraphQLJSONObject } from 'graphql-scalars'; 2 | 3 | export * from './date'; 4 | export * from './decimal'; 5 | export * from './time'; 6 | export * from './iso-string'; 7 | export * from './nano-duration'; 8 | export * from './nano-timestamp'; 9 | -------------------------------------------------------------------------------- /src/packages/scalars/src/nano-duration.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLScalarType } from 'graphql'; 2 | import { GraphQLBigInt } from 'graphql-scalars'; 3 | 4 | // The underlying type is BigInt, but we're using a custom name and description for display purposes 5 | const GraphQLNanoDurationConfig = { 6 | ...GraphQLBigInt, 7 | name: 'NanoDuration', 8 | description: 'A duration in nanoseconds', 9 | extensions: { 10 | type: 'integer', 11 | }, 12 | }; 13 | 14 | export const GraphQLNanoDuration = new GraphQLScalarType(GraphQLNanoDurationConfig); 15 | -------------------------------------------------------------------------------- /src/packages/scalars/src/nano-timestamp.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLScalarType } from 'graphql'; 2 | import { GraphQLBigInt } from 'graphql-scalars'; 3 | 4 | // The underlying type is BigInt, but we're using a custom name and description for display purposes 5 | const GraphQLNanoTimestampConfig = { 6 | ...GraphQLBigInt, 7 | name: 'NanoTimestamp', 8 | description: 'A timestamp in nanoseconds', 9 | extensions: { 10 | type: 'integer', 11 | }, 12 | }; 13 | 14 | export const GraphQLNanoTimestamp = new GraphQLScalarType(GraphQLNanoTimestampConfig); 15 | -------------------------------------------------------------------------------- /src/packages/scalars/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./lib" 6 | }, 7 | "include": ["./src"] 8 | } 9 | -------------------------------------------------------------------------------- /src/packages/server/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/packages/server/README.md: -------------------------------------------------------------------------------- 1 | # `@exogee/graphweaver-server` 2 | 3 | Server support for `@exogee/graphweaver` 4 | 5 | ## Documentation 6 | 7 | Comprehensive documentation and usage examples can be found on our [Docs Site](https://graphweaver.com/docs). It covers installation instructions, detailed API documentation, and guides to help you get started with Graphweaver. 8 | 9 | ## Graphweaver CLI `graphweaver` 10 | 11 | The Graphweaver Command Line Interface (CLI) tool enables you to set up and manage Graphweaver using commands in your command-line shell. Check the `graphweaver` npm package [here.](https://www.npmjs.com/package/graphweaver) 12 | -------------------------------------------------------------------------------- /src/packages/server/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | 5 | const entryPoints = await glob('./src/**/*.ts'); 6 | await esbuild.build({ 7 | outdir: 'lib', 8 | format: 'cjs', 9 | platform: 'node', 10 | sourcemap: 'linked', 11 | entryPoints, 12 | }); 13 | })(); 14 | -------------------------------------------------------------------------------- /src/packages/server/src/apollo-plugins/apollo-plugin-manager.ts: -------------------------------------------------------------------------------- 1 | import { ApolloServerPlugin, BaseContext } from '@apollo/server'; 2 | 3 | class ApolloPluginManager { 4 | private plugins: Map> = new Map(); 5 | 6 | addPlugin(name: string, plugin: ApolloServerPlugin) { 7 | this.plugins.set(name, plugin); 8 | } 9 | 10 | getPlugins(): Set> { 11 | return new Set(this.plugins.values()); 12 | } 13 | } 14 | 15 | export const apolloPluginManager = new ApolloPluginManager(); 16 | -------------------------------------------------------------------------------- /src/packages/server/src/apollo-plugins/index.ts: -------------------------------------------------------------------------------- 1 | export { LogErrors } from './log-errors'; 2 | export { LogRequests } from './log-requests'; 3 | export { corsPlugin } from './cors'; 4 | export { dedupeGraphQL } from './graphql-deduplicator'; 5 | 6 | export type { CorsPluginOptions } from './cors'; 7 | -------------------------------------------------------------------------------- /src/packages/server/src/apollo-plugins/log-errors.ts: -------------------------------------------------------------------------------- 1 | import { ApolloServerPlugin } from '@apollo/server'; 2 | import { logger } from '@exogee/logger'; 3 | 4 | // This plugin ensures we log errors 5 | export const LogErrors: ApolloServerPlugin = { 6 | async unexpectedErrorProcessingRequest({ error }) { 7 | logger.error(error, 'Unexpected error processing request.'); 8 | }, 9 | 10 | async requestDidStart() { 11 | return { 12 | async didEncounterErrors({ errors }) { 13 | for (const error of errors) { 14 | logger.error(error, 'Unexpected error processing request.'); 15 | } 16 | }, 17 | }; 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /src/packages/server/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@apollo/server'; 2 | export * from './plugin-manager'; 3 | export * from './apollo-plugins/apollo-plugin-manager'; 4 | export * from './config'; 5 | 6 | export { default } from './server'; 7 | -------------------------------------------------------------------------------- /src/packages/server/src/integrations/index.ts: -------------------------------------------------------------------------------- 1 | export * from './fastify'; 2 | export * from './lambda'; 3 | -------------------------------------------------------------------------------- /src/packages/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "rootDir": "./src", 6 | "noUnusedLocals": false 7 | }, 8 | "include": ["./src/**/*.ts"], 9 | "references": [{ "path": "../core" }, { "path": "../logger" }] 10 | } 11 | -------------------------------------------------------------------------------- /src/packages/server/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | include: ['src/**/*.{test,spec}.?(c|m)[jt]s?(x)'], 6 | }, 7 | }); 8 | -------------------------------------------------------------------------------- /src/packages/storage-provider/README.md: -------------------------------------------------------------------------------- 1 | # `@exogee/graphweaver-storage-provider 2 | 3 | This package enables using a storage provider, such as AWS S3 buckets, to upload and store media. 4 | -------------------------------------------------------------------------------- /src/packages/storage-provider/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | const entryPoints = await glob('./src/**/*.ts'); 5 | await esbuild.build({ 6 | outdir: 'lib', 7 | format: 'cjs', 8 | platform: 'node', 9 | sourcemap: 'linked', 10 | entryPoints, 11 | }); 12 | })(); 13 | -------------------------------------------------------------------------------- /src/packages/storage-provider/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './storageProvider'; 2 | export * from './decorators/media-field'; 3 | -------------------------------------------------------------------------------- /src/packages/storage-provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "rootDir": "./src", 6 | "outDir": "./lib" 7 | }, 8 | "references": [{ "path": "../core" }, { "path": "../logger" }, { "path": "../scalars" }] 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/vite-plugin-graphweaver/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ignorePatterns: ['.deploy/**', '.build/**', 'lib/**'], 3 | }; 4 | -------------------------------------------------------------------------------- /src/packages/vite-plugin-graphweaver/.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true -------------------------------------------------------------------------------- /src/packages/vite-plugin-graphweaver/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | 5 | const entryPoints = await glob('./src/**/*.ts'); 6 | await esbuild.build({ 7 | outdir: 'lib', 8 | format: 'cjs', 9 | platform: 'node', 10 | sourcemap: 'linked', 11 | entryPoints, 12 | }); 13 | })(); 14 | -------------------------------------------------------------------------------- /src/packages/vite-plugin-graphweaver/src/loaders/auth.ts: -------------------------------------------------------------------------------- 1 | import { config } from '@exogee/graphweaver-config'; 2 | 3 | const defaultReturn = `export const loadRoutes = () => []; 4 | export const SignOut = () => null; 5 | export const customFields = new Map();`; 6 | 7 | export const loadAuth = async () => { 8 | try { 9 | const { adminUI } = config(); 10 | if (adminUI.auth?.primaryMethods) { 11 | return `export { loadRoutes, SignOut, customFields } from '@exogee/graphweaver-auth-ui-components';`; 12 | } else { 13 | return defaultReturn; 14 | } 15 | } catch { 16 | console.warn('No custom pages component found'); 17 | return defaultReturn; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /src/packages/vite-plugin-graphweaver/src/loaders/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auth'; 2 | export * from './csv-export-overrides'; 3 | export * from './custom-fields'; 4 | export * from './custom-pages'; 5 | -------------------------------------------------------------------------------- /src/packages/vite-plugin-graphweaver/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./lib" 6 | }, 7 | "include": ["./src"], 8 | "references": [{ "path": "../config" }] 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/xero/README.md: -------------------------------------------------------------------------------- 1 | # `@exogee/graphweaver-xero` 2 | 3 | Xero adapter package for Graphweaver 4 | 5 | ## Documentation 6 | 7 | Comprehensive documentation and usage examples can be found on our [Docs Site](https://graphweaver.com/docs). It covers installation instructions, detailed API documentation, and guides to help you get started with Graphweaver. 8 | 9 | ## Graphweaver CLI `graphweaver` 10 | 11 | The Graphweaver Command Line Interface (CLI) tool enables you to set up and manage Graphweaver using commands in your command-line shell. Check the `graphweaver` npm package [here.](https://www.npmjs.com/package/graphweaver) 12 | -------------------------------------------------------------------------------- /src/packages/xero/build.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | const esbuild = await import('esbuild'); 3 | const { glob } = await import('glob'); 4 | 5 | const entryPoints = await glob('./src/**/*.ts'); 6 | await esbuild.build({ 7 | outdir: 'lib', 8 | format: 'cjs', 9 | platform: 'node', 10 | sourcemap: 'linked', 11 | entryPoints, 12 | }); 13 | })(); 14 | -------------------------------------------------------------------------------- /src/packages/xero/src/apollo-plugins/index.ts: -------------------------------------------------------------------------------- 1 | export * from './xero-auth-apollo-plugin'; 2 | -------------------------------------------------------------------------------- /src/packages/xero/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './apollo-plugins'; 2 | export * from './provider'; 3 | -------------------------------------------------------------------------------- /src/packages/xero/src/provider/index.ts: -------------------------------------------------------------------------------- 1 | export * from './provider'; 2 | -------------------------------------------------------------------------------- /src/packages/xero/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "rootDir": "./src", 6 | "noUnusedLocals": false 7 | }, 8 | "include": ["./src"], 9 | "references": [{ "path": "../core" }, { "path": "../logger" }] 10 | } 11 | -------------------------------------------------------------------------------- /src/pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | # all packages in subdirs of packages/ and components/ 3 | - 'packages/**' 4 | - 'examples/**' 5 | # exclude test packages 6 | - '!examples/federation/integration' 7 | - '!packages/end-to-end/app' 8 | - '!packages/end-to-end/local_modules/**' 9 | --------------------------------------------------------------------------------