create-nexst-monorepo 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1727 -0
- package/package.json +37 -0
- package/template/.agents/plugins/marketplace.json +21 -0
- package/template/.claude/settings.json +6 -0
- package/template/.claude/skills/frontend-design/LICENSE.txt +177 -0
- package/template/.claude/skills/frontend-design/SKILL.md +154 -0
- package/template/.claude/skills/theme-factory/SKILL.md +95 -0
- package/template/.claude/skills/theme-factory/references/schema.md +104 -0
- package/template/.claude/skills/theme-factory/scripts/theme.mjs +261 -0
- package/template/.dockerignore +43 -0
- package/template/.editorconfig +10 -0
- package/template/.github/workflows/ci.yaml +289 -0
- package/template/.github/workflows/publish-app.yaml +66 -0
- package/template/.github/workflows/publish.yaml +148 -0
- package/template/.github/workflows/snyk.yaml +34 -0
- package/template/.vscode/settings.json +8 -0
- package/template/AGENTS.md +42 -0
- package/template/Dockerfile.base +9 -0
- package/template/README.md +54 -0
- package/template/_gitignore +10 -0
- package/template/apps/api/.env.example +32 -0
- package/template/apps/api/AGENTS.md +44 -0
- package/template/apps/api/Dockerfile +69 -0
- package/template/apps/api/_gitignore +8 -0
- package/template/apps/api/knip.config.ts +22 -0
- package/template/apps/api/kustomize/base/application.properties +16 -0
- package/template/apps/api/kustomize/base/deployment.yaml +94 -0
- package/template/apps/api/kustomize/base/kustomization.yaml +17 -0
- package/template/apps/api/kustomize/base/service.yaml +10 -0
- package/template/apps/api/kustomize/overlays/prod/kustomization.yaml +17 -0
- package/template/apps/api/kustomize/overlays/staging/application.properties +1 -0
- package/template/apps/api/kustomize/overlays/staging/kustomization.yaml +21 -0
- package/template/apps/api/kustomize/secret.keys +14 -0
- package/template/apps/api/oxfmt.config.ts +8 -0
- package/template/apps/api/oxlint.config.ts +107 -0
- package/template/apps/api/package.json +79 -0
- package/template/apps/api/prisma/migrations/20260927000000_init/migration.sql +113 -0
- package/template/apps/api/prisma/migrations/migration_lock.toml +3 -0
- package/template/apps/api/prisma/schema.prisma +113 -0
- package/template/apps/api/prisma.config.ts +7 -0
- package/template/apps/api/scripts/auth.cli.ts +19 -0
- package/template/apps/api/scripts/seal-secret.sh +171 -0
- package/template/apps/api/sonar-project.properties +9 -0
- package/template/apps/api/src/app-info/app-info.dto.ts +10 -0
- package/template/apps/api/src/app-info/app-info.module.ts +7 -0
- package/template/apps/api/src/app-info/app-info.resolver.spec.ts +14 -0
- package/template/apps/api/src/app-info/app-info.resolver.ts +21 -0
- package/template/apps/api/src/app.module.spec.ts +93 -0
- package/template/apps/api/src/app.module.ts +77 -0
- package/template/apps/api/src/auth/auth.guard.spec.ts +90 -0
- package/template/apps/api/src/auth/auth.guard.ts +97 -0
- package/template/apps/api/src/auth/auth.ts +129 -0
- package/template/apps/api/src/auth/decorator/allow-anonymous.decorator.ts +17 -0
- package/template/apps/api/src/auth/decorator/is-email-verified.decorator.spec.ts +41 -0
- package/template/apps/api/src/auth/decorator/is-email-verified.decorator.ts +20 -0
- package/template/apps/api/src/auth/decorator/roles.decorator.ts +27 -0
- package/template/apps/api/src/auth/testing/make-session.ts +31 -0
- package/template/apps/api/src/auth/types/auth.types.ts +27 -0
- package/template/apps/api/src/bootstrap/register-graphql-enums.ts +12 -0
- package/template/apps/api/src/bootstrap/security.ts +24 -0
- package/template/apps/api/src/bootstrap/swagger.ts +28 -0
- package/template/apps/api/src/config/app.config.spec.ts +22 -0
- package/template/apps/api/src/config/app.config.ts +122 -0
- package/template/apps/api/src/config/graphql-depth-limit.ts +103 -0
- package/template/apps/api/src/config/graphql.config.ts +77 -0
- package/template/apps/api/src/config/resources/app.yaml +29 -0
- package/template/apps/api/src/errors/app-parse-uuid.pipe.ts +27 -0
- package/template/apps/api/src/errors/app.exception.ts +47 -0
- package/template/apps/api/src/errors/error-code.enum.ts +54 -0
- package/template/apps/api/src/errors/http-status-fallback-code.util.ts +27 -0
- package/template/apps/api/src/errors/validation-exception.factory.ts +43 -0
- package/template/apps/api/src/health/health.controller.spec.ts +82 -0
- package/template/apps/api/src/health/health.controller.ts +57 -0
- package/template/apps/api/src/health/health.module.ts +12 -0
- package/template/apps/api/src/logging/context-logger.ts +18 -0
- package/template/apps/api/src/logging/logger.config.ts +23 -0
- package/template/apps/api/src/logging/logging.module.ts +22 -0
- package/template/apps/api/src/mail/mail.module.ts +12 -0
- package/template/apps/api/src/mail/mail.service.spec.ts +47 -0
- package/template/apps/api/src/mail/mail.service.ts +123 -0
- package/template/apps/api/src/main.ts +41 -0
- package/template/apps/api/src/prisma/prisma.module.ts +12 -0
- package/template/apps/api/src/prisma/prisma.service.spec.ts +136 -0
- package/template/apps/api/src/prisma/prisma.service.ts +138 -0
- package/template/apps/api/src/queue/dto/enqueue-example.input.ts +11 -0
- package/template/apps/api/src/queue/example-queue.resolver.ts +14 -0
- package/template/apps/api/src/queue/example-queue.service.spec.ts +21 -0
- package/template/apps/api/src/queue/example-queue.service.ts +32 -0
- package/template/apps/api/src/queue/queue.module.ts +27 -0
- package/template/apps/api/src/r2/r2.module.ts +12 -0
- package/template/apps/api/src/r2/r2.service.spec.ts +117 -0
- package/template/apps/api/src/r2/r2.service.ts +131 -0
- package/template/apps/api/src/user/dto/user.dto.ts +26 -0
- package/template/apps/api/src/user/user.module.ts +10 -0
- package/template/apps/api/src/user/user.resolver.spec.ts +18 -0
- package/template/apps/api/src/user/user.resolver.ts +24 -0
- package/template/apps/api/src/utils/catch-everything-exception.filter.spec.ts +292 -0
- package/template/apps/api/src/utils/catch-everything-exception.filter.ts +70 -0
- package/template/apps/api/src/utils/error-handler.util.spec.ts +20 -0
- package/template/apps/api/src/utils/error-handler.util.ts +12 -0
- package/template/apps/api/src/utils/escape-like-pattern.util.spec.ts +29 -0
- package/template/apps/api/src/utils/escape-like-pattern.util.ts +11 -0
- package/template/apps/api/src/utils/pagination.input.ts +20 -0
- package/template/apps/api/src/utils/prisma-exception.filter.spec.ts +186 -0
- package/template/apps/api/src/utils/prisma-exception.filter.ts +45 -0
- package/template/apps/api/src/utils/prisma-graphql-exception.filter.spec.ts +216 -0
- package/template/apps/api/src/utils/prisma-graphql-exception.filter.ts +43 -0
- package/template/apps/api/tests/app.e2e-spec.ts +35 -0
- package/template/apps/api/tests/auth.e2e-spec.ts +38 -0
- package/template/apps/api/tests/helpers/api.ts +27 -0
- package/template/apps/api/tsconfig.json +11 -0
- package/template/apps/api/vitest.config.e2e.ts +16 -0
- package/template/apps/api/vitest.config.ts +40 -0
- package/template/apps/web/.env.example +7 -0
- package/template/apps/web/.storybook/decorators.tsx +38 -0
- package/template/apps/web/.storybook/main.ts +17 -0
- package/template/apps/web/.storybook/preview.ts +38 -0
- package/template/apps/web/.storybook/vitest.setup.ts +5 -0
- package/template/apps/web/AGENTS.md +29 -0
- package/template/apps/web/Dockerfile +49 -0
- package/template/apps/web/_gitignore +16 -0
- package/template/apps/web/knip.config.ts +15 -0
- package/template/apps/web/kustomize/base/application.properties +5 -0
- package/template/apps/web/kustomize/base/deployment.yaml +60 -0
- package/template/apps/web/kustomize/base/kustomization.yaml +17 -0
- package/template/apps/web/kustomize/base/service.yaml +10 -0
- package/template/apps/web/kustomize/overlays/prod/kustomization.yaml +12 -0
- package/template/apps/web/kustomize/overlays/staging/application.properties +2 -0
- package/template/apps/web/kustomize/overlays/staging/kustomization.yaml +18 -0
- package/template/apps/web/messages/de.json +124 -0
- package/template/apps/web/messages/en.json +124 -0
- package/template/apps/web/next-env.d.ts +7 -0
- package/template/apps/web/next.config.ts +39 -0
- package/template/apps/web/oxfmt.config.ts +9 -0
- package/template/apps/web/oxlint.config.ts +36 -0
- package/template/apps/web/package.json +80 -0
- package/template/apps/web/playwright.config.ts +34 -0
- package/template/apps/web/postcss.config.mjs +7 -0
- package/template/apps/web/sonar-project.properties +9 -0
- package/template/apps/web/src/app/[locale]/(auth)/recovery/page.tsx +22 -0
- package/template/apps/web/src/app/[locale]/(auth)/reset-password/page.tsx +29 -0
- package/template/apps/web/src/app/[locale]/(auth)/sign-in/page.tsx +24 -0
- package/template/apps/web/src/app/[locale]/(auth)/sign-up/page.tsx +24 -0
- package/template/apps/web/src/app/[locale]/(auth)/verify/page.tsx +24 -0
- package/template/apps/web/src/app/[locale]/dashboard/page.tsx +34 -0
- package/template/apps/web/src/app/[locale]/layout.tsx +60 -0
- package/template/apps/web/src/app/[locale]/page.tsx +23 -0
- package/template/apps/web/src/app/api/health/route.ts +3 -0
- package/template/apps/web/src/app/global-error.tsx +19 -0
- package/template/apps/web/src/app/globals.css +98 -0
- package/template/apps/web/src/app/icon.svg +1 -0
- package/template/apps/web/src/app/robots.ts +15 -0
- package/template/apps/web/src/app/sitemap.ts +24 -0
- package/template/apps/web/src/components/alert/alert.stories.tsx +25 -0
- package/template/apps/web/src/components/alert/alert.tsx +50 -0
- package/template/apps/web/src/components/avatar/avatar.stories.tsx +116 -0
- package/template/apps/web/src/components/avatar/avatar.tsx +88 -0
- package/template/apps/web/src/components/button/button-variants.ts +28 -0
- package/template/apps/web/src/components/button/button.stories.tsx +33 -0
- package/template/apps/web/src/components/button/button.tsx +32 -0
- package/template/apps/web/src/components/checkbox/checkbox.stories.tsx +312 -0
- package/template/apps/web/src/components/checkbox/checkbox.tsx +38 -0
- package/template/apps/web/src/components/dialog/danger-panel.stories.tsx +41 -0
- package/template/apps/web/src/components/dialog/danger-panel.tsx +32 -0
- package/template/apps/web/src/components/dialog/dialog.stories.tsx +239 -0
- package/template/apps/web/src/components/dialog/dialog.tsx +136 -0
- package/template/apps/web/src/components/dialog-buttons.stories.tsx +55 -0
- package/template/apps/web/src/components/dialog-buttons.tsx +48 -0
- package/template/apps/web/src/components/drawer/drawer.stories.tsx +251 -0
- package/template/apps/web/src/components/drawer/drawer.tsx +120 -0
- package/template/apps/web/src/components/dropdown-menu/dropdown-menu.stories.tsx +329 -0
- package/template/apps/web/src/components/dropdown-menu/dropdown-menu.tsx +263 -0
- package/template/apps/web/src/components/empty-state.stories.tsx +49 -0
- package/template/apps/web/src/components/empty-state.tsx +33 -0
- package/template/apps/web/src/components/field-group.stories.tsx +47 -0
- package/template/apps/web/src/components/field-group.tsx +20 -0
- package/template/apps/web/src/components/field-label.stories.tsx +34 -0
- package/template/apps/web/src/components/field-label.tsx +28 -0
- package/template/apps/web/src/components/icons.tsx +25 -0
- package/template/apps/web/src/components/input/input-otp.stories.tsx +86 -0
- package/template/apps/web/src/components/input/input-otp.tsx +184 -0
- package/template/apps/web/src/components/input/input.stories.tsx +35 -0
- package/template/apps/web/src/components/input/input.tsx +180 -0
- package/template/apps/web/src/components/popover/popover.stories.tsx +479 -0
- package/template/apps/web/src/components/popover/popover.tsx +45 -0
- package/template/apps/web/src/components/responsive-dialog/responsive-dialog.stories.tsx +307 -0
- package/template/apps/web/src/components/responsive-dialog/responsive-dialog.tsx +96 -0
- package/template/apps/web/src/components/searchbar/searchbar.stories.tsx +59 -0
- package/template/apps/web/src/components/searchbar/searchbar.tsx +64 -0
- package/template/apps/web/src/components/select/select.stories.tsx +293 -0
- package/template/apps/web/src/components/select/select.tsx +445 -0
- package/template/apps/web/src/components/skeleton/skeleton.stories.tsx +76 -0
- package/template/apps/web/src/components/skeleton/skeleton.tsx +13 -0
- package/template/apps/web/src/components/spinner/spinner.tsx +18 -0
- package/template/apps/web/src/components/switch/switch.stories.tsx +71 -0
- package/template/apps/web/src/components/switch/switch.tsx +35 -0
- package/template/apps/web/src/components/tabs/tabs.stories.tsx +209 -0
- package/template/apps/web/src/components/tabs/tabs.tsx +69 -0
- package/template/apps/web/src/components/tabs/url-tabs.stories.tsx +68 -0
- package/template/apps/web/src/components/tabs/url-tabs.tsx +42 -0
- package/template/apps/web/src/components/textarea/textarea.stories.tsx +144 -0
- package/template/apps/web/src/components/textarea/textarea.tsx +115 -0
- package/template/apps/web/src/components/toast/toaster.tsx +38 -0
- package/template/apps/web/src/components/tooltip/tooltip.stories.tsx +237 -0
- package/template/apps/web/src/components/tooltip/tooltip.tsx +49 -0
- package/template/apps/web/src/config/csp.ts +59 -0
- package/template/apps/web/src/config/routes.ts +14 -0
- package/template/apps/web/src/config/site.ts +5 -0
- package/template/apps/web/src/env.ts +15 -0
- package/template/apps/web/src/features/auth/auth-card.tsx +20 -0
- package/template/apps/web/src/features/auth/auth-divider.tsx +14 -0
- package/template/apps/web/src/features/auth/google-auth-button.tsx +49 -0
- package/template/apps/web/src/features/auth/google-one-tap.tsx +23 -0
- package/template/apps/web/src/features/auth/lib/auth-error.test.ts +22 -0
- package/template/apps/web/src/features/auth/lib/auth-error.ts +16 -0
- package/template/apps/web/src/features/auth/lib/return-to.test.ts +41 -0
- package/template/apps/web/src/features/auth/lib/return-to.ts +19 -0
- package/template/apps/web/src/features/auth/lib/validator.test.ts +45 -0
- package/template/apps/web/src/features/auth/lib/validator.ts +49 -0
- package/template/apps/web/src/features/auth/passkey-settings.tsx +106 -0
- package/template/apps/web/src/features/auth/recovery-form.tsx +61 -0
- package/template/apps/web/src/features/auth/resend-verification-button.tsx +36 -0
- package/template/apps/web/src/features/auth/reset-password-form.tsx +62 -0
- package/template/apps/web/src/features/auth/sign-in-form.stories.tsx +22 -0
- package/template/apps/web/src/features/auth/sign-in-form.tsx +116 -0
- package/template/apps/web/src/features/auth/sign-out-button.tsx +26 -0
- package/template/apps/web/src/features/auth/sign-up-form.tsx +107 -0
- package/template/apps/web/src/features/shared/provider.tsx +16 -0
- package/template/apps/web/src/features/shared/site-header.tsx +48 -0
- package/template/apps/web/src/features/shared/theme-toggle.tsx +24 -0
- package/template/apps/web/src/i18n/navigation.ts +5 -0
- package/template/apps/web/src/i18n/request.ts +21 -0
- package/template/apps/web/src/i18n/routing.ts +6 -0
- package/template/apps/web/src/lib/auth-client.ts +19 -0
- package/template/apps/web/src/lib/auth-server.ts +46 -0
- package/template/apps/web/src/lib/auth.ts +8 -0
- package/template/apps/web/src/lib/codegen.ts +30 -0
- package/template/apps/web/src/lib/graphql-client.ts +29 -0
- package/template/apps/web/src/lib/graphql-server.ts +28 -0
- package/template/apps/web/src/lib/graphql-utils.test.ts +32 -0
- package/template/apps/web/src/lib/graphql-utils.ts +76 -0
- package/template/apps/web/src/lib/hooks/use-media-query.ts +21 -0
- package/template/apps/web/src/lib/metadata.ts +17 -0
- package/template/apps/web/src/lib/network-error.test.ts +30 -0
- package/template/apps/web/src/lib/network-error.ts +17 -0
- package/template/apps/web/src/lib/proxy-utils.ts +42 -0
- package/template/apps/web/src/lib/query-client.ts +29 -0
- package/template/apps/web/src/lib/utils.ts +5 -0
- package/template/apps/web/src/proxy.ts +57 -0
- package/template/apps/web/test-results/.last-run.json +4 -0
- package/template/apps/web/tests/auth.spec.ts +17 -0
- package/template/apps/web/tests/csp-theme-script.spec.ts +37 -0
- package/template/apps/web/tests/home.spec.ts +25 -0
- package/template/apps/web/tsconfig.build.json +4 -0
- package/template/apps/web/tsconfig.json +28 -0
- package/template/apps/web/vitest.config.ts +40 -0
- package/template/apps/web/vitest.shims.d.ts +1 -0
- package/template/apps/worker/.env.example +4 -0
- package/template/apps/worker/AGENTS.md +11 -0
- package/template/apps/worker/Dockerfile +35 -0
- package/template/apps/worker/knip.config.ts +3 -0
- package/template/apps/worker/kustomize/base/application.properties +4 -0
- package/template/apps/worker/kustomize/base/deployment.yaml +62 -0
- package/template/apps/worker/kustomize/base/kustomization.yaml +16 -0
- package/template/apps/worker/kustomize/overlays/prod/kustomization.yaml +12 -0
- package/template/apps/worker/kustomize/overlays/staging/application.properties +1 -0
- package/template/apps/worker/kustomize/overlays/staging/kustomization.yaml +18 -0
- package/template/apps/worker/oxfmt.config.ts +8 -0
- package/template/apps/worker/oxlint.config.ts +15 -0
- package/template/apps/worker/package.json +33 -0
- package/template/apps/worker/sonar-project.properties +8 -0
- package/template/apps/worker/src/env.ts +13 -0
- package/template/apps/worker/src/lib/graceful-shutdown.ts +27 -0
- package/template/apps/worker/src/lib/logger.ts +20 -0
- package/template/apps/worker/src/main.ts +17 -0
- package/template/apps/worker/src/processors/example-processor.ts +15 -0
- package/template/apps/worker/src/worker/redis.ts +19 -0
- package/template/apps/worker/src/worker/worker.ts +37 -0
- package/template/apps/worker/tests/example-processor.test.ts +13 -0
- package/template/apps/worker/tests/graceful-shutdown.test.ts +34 -0
- package/template/apps/worker/tsconfig.json +4 -0
- package/template/apps/worker/vitest.config.ts +13 -0
- package/template/bun.lock +3053 -0
- package/template/bunfig.toml +2 -0
- package/template/compose.yaml +53 -0
- package/template/docker-bake.hcl +86 -0
- package/template/package.json +47 -0
- package/template/packages/lint/knip.ts +40 -0
- package/template/packages/lint/oxfmt.ts +8 -0
- package/template/packages/lint/oxlint.ts +136 -0
- package/template/packages/lint/package.json +13 -0
- package/template/packages/queues/oxfmt.config.ts +8 -0
- package/template/packages/queues/oxlint.config.ts +7 -0
- package/template/packages/queues/package.json +15 -0
- package/template/packages/queues/src/example-job.ts +11 -0
- package/template/packages/queues/src/index.ts +3 -0
- package/template/packages/queues/src/queue-names.ts +2 -0
- package/template/packages/queues/src/redis-connection.ts +27 -0
- package/template/packages/queues/tsconfig.json +4 -0
- package/template/packages/tsconfig/base.json +23 -0
- package/template/packages/tsconfig/node.json +11 -0
- package/template/packages/tsconfig/package.json +4 -0
- package/template/turbo.json +50 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: nexst
|
|
2
|
+
|
|
3
|
+
configs:
|
|
4
|
+
postgres_init:
|
|
5
|
+
content: |
|
|
6
|
+
CREATE SCHEMA IF NOT EXISTS nexst_user AUTHORIZATION nexst_user;
|
|
7
|
+
ALTER ROLE nexst_user SET search_path = 'nexst_user';
|
|
8
|
+
|
|
9
|
+
services:
|
|
10
|
+
postgres:
|
|
11
|
+
image: postgres:18-alpine
|
|
12
|
+
container_name: nexst_dev_postgres
|
|
13
|
+
environment:
|
|
14
|
+
POSTGRES_USER: nexst_user
|
|
15
|
+
POSTGRES_PASSWORD: test-pw
|
|
16
|
+
POSTGRES_DB: nexst_db
|
|
17
|
+
TZ: Europe/Berlin
|
|
18
|
+
ports: ["5432:5432"]
|
|
19
|
+
volumes: [nexst_dev_pgdata:/var/lib/postgresql]
|
|
20
|
+
configs:
|
|
21
|
+
[{ source: postgres_init, target: /docker-entrypoint-initdb.d/init.sql }]
|
|
22
|
+
healthcheck:
|
|
23
|
+
test: [CMD-SHELL, "pg_isready -U nexst_user -d nexst_db"]
|
|
24
|
+
interval: 5s
|
|
25
|
+
timeout: 3s
|
|
26
|
+
retries: 10
|
|
27
|
+
# @if worker
|
|
28
|
+
|
|
29
|
+
redis:
|
|
30
|
+
image: redis:8-alpine
|
|
31
|
+
container_name: nexst_dev_redis
|
|
32
|
+
command: redis-server --appendonly yes
|
|
33
|
+
ports: ["6379:6379"]
|
|
34
|
+
volumes: [nexst_dev_redis:/data]
|
|
35
|
+
healthcheck:
|
|
36
|
+
test: [CMD, redis-cli, ping]
|
|
37
|
+
interval: 5s
|
|
38
|
+
timeout: 3s
|
|
39
|
+
retries: 10
|
|
40
|
+
# @endif
|
|
41
|
+
# @if auth
|
|
42
|
+
|
|
43
|
+
mailhog:
|
|
44
|
+
image: mailhog/mailhog:v1.0.1
|
|
45
|
+
container_name: nexst_dev_mailhog
|
|
46
|
+
ports: ["1025:1025", "8025:8025"]
|
|
47
|
+
# @endif
|
|
48
|
+
|
|
49
|
+
volumes:
|
|
50
|
+
nexst_dev_pgdata:
|
|
51
|
+
# @if worker
|
|
52
|
+
nexst_dev_redis:
|
|
53
|
+
# @endif
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
variable "BUN_VERSION" {
|
|
2
|
+
default = "1.4.2"
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
variable "NEXT_PUBLIC_HOST_URL" {
|
|
6
|
+
default = null
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
variable "NEXT_PUBLIC_API_URL" {
|
|
10
|
+
default = null
|
|
11
|
+
}
|
|
12
|
+
# @if auth
|
|
13
|
+
|
|
14
|
+
variable "NEXT_PUBLIC_GOOGLE_CLIENT_ID" {
|
|
15
|
+
default = null
|
|
16
|
+
}
|
|
17
|
+
# @endif
|
|
18
|
+
|
|
19
|
+
group "default" {
|
|
20
|
+
# @if worker
|
|
21
|
+
targets = ["api", "worker", "web"]
|
|
22
|
+
# @endif
|
|
23
|
+
# @if !worker
|
|
24
|
+
# targets = ["api", "web"]
|
|
25
|
+
# @endif
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
target "docker-metadata-action" {
|
|
29
|
+
tags = ["nexst:local"]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
target "base" {
|
|
33
|
+
dockerfile = "Dockerfile.base"
|
|
34
|
+
args = {
|
|
35
|
+
BUN_VERSION = BUN_VERSION
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
target "_app" {
|
|
40
|
+
inherits = ["docker-metadata-action"]
|
|
41
|
+
contexts = {
|
|
42
|
+
toolchain = "target:base"
|
|
43
|
+
}
|
|
44
|
+
platforms = ["linux/arm64"]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
target "api" {
|
|
48
|
+
inherits = ["_app"]
|
|
49
|
+
dockerfile = "apps/api/Dockerfile"
|
|
50
|
+
target = "runtime"
|
|
51
|
+
args = {
|
|
52
|
+
BUN_VERSION = BUN_VERSION
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
target "api-migrate" {
|
|
57
|
+
inherits = ["_app"]
|
|
58
|
+
dockerfile = "apps/api/Dockerfile"
|
|
59
|
+
target = "migrator"
|
|
60
|
+
args = {
|
|
61
|
+
BUN_VERSION = BUN_VERSION
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
# @if worker
|
|
65
|
+
|
|
66
|
+
target "worker" {
|
|
67
|
+
inherits = ["_app"]
|
|
68
|
+
dockerfile = "apps/worker/Dockerfile"
|
|
69
|
+
args = {
|
|
70
|
+
BUN_VERSION = BUN_VERSION
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
# @endif
|
|
74
|
+
|
|
75
|
+
target "web" {
|
|
76
|
+
inherits = ["_app"]
|
|
77
|
+
dockerfile = "apps/web/Dockerfile"
|
|
78
|
+
args = {
|
|
79
|
+
BUN_VERSION = BUN_VERSION
|
|
80
|
+
NEXT_PUBLIC_HOST_URL = NEXT_PUBLIC_HOST_URL
|
|
81
|
+
NEXT_PUBLIC_API_URL = NEXT_PUBLIC_API_URL
|
|
82
|
+
# @if auth
|
|
83
|
+
NEXT_PUBLIC_GOOGLE_CLIENT_ID = NEXT_PUBLIC_GOOGLE_CLIENT_ID
|
|
84
|
+
# @endif
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nexst",
|
|
3
|
+
"private": true,
|
|
4
|
+
"workspaces": [
|
|
5
|
+
"apps/*",
|
|
6
|
+
"packages/*"
|
|
7
|
+
],
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "docker compose up -d --wait && turbo run dev",
|
|
10
|
+
"infra:down": "docker compose down",
|
|
11
|
+
"build": "turbo run build",
|
|
12
|
+
"lint": "turbo run lint",
|
|
13
|
+
"lint:fix": "turbo run lint:fix",
|
|
14
|
+
"fmt": "turbo run fmt",
|
|
15
|
+
"fmt:check": "turbo run fmt:check",
|
|
16
|
+
"lint:ts": "turbo run lint:ts",
|
|
17
|
+
"unused": "turbo run unused --continue=always",
|
|
18
|
+
"test:unit": "turbo run test:unit"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@nexst/lint": "workspace:*",
|
|
22
|
+
"@nexst/tsconfig": "workspace:*",
|
|
23
|
+
"@vitest/coverage-v8": "^5.0.2",
|
|
24
|
+
"@vitest/ui": "^5.0.2",
|
|
25
|
+
"eslint-plugin-perfectionist": "^5.12.1",
|
|
26
|
+
"eslint-plugin-regexp": "^3.3.1",
|
|
27
|
+
"eslint-plugin-security": "^4.0.1",
|
|
28
|
+
"eslint-plugin-sonarjs": "^4.2.1",
|
|
29
|
+
"knip": "^6.38.0",
|
|
30
|
+
"oxfmt": "^0.70.0",
|
|
31
|
+
"oxlint": "^1.85.0",
|
|
32
|
+
"oxlint-tsgolint": "^7.0.2003",
|
|
33
|
+
"turbo": "2.11.4",
|
|
34
|
+
"typescript": "^7.0.2",
|
|
35
|
+
"vitest": "^5.0.2"
|
|
36
|
+
},
|
|
37
|
+
"packageManager": "bun@1.4.2",
|
|
38
|
+
"trustedDependencies": [
|
|
39
|
+
"@nestjs/core",
|
|
40
|
+
"@prisma/engines",
|
|
41
|
+
"@swc/core",
|
|
42
|
+
"esbuild",
|
|
43
|
+
"msgpackr-extract",
|
|
44
|
+
"prisma",
|
|
45
|
+
"sharp"
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
interface KnipConfigOverrides {
|
|
2
|
+
entry?: string[];
|
|
3
|
+
ignoreBinaries?: string[];
|
|
4
|
+
ignoreDependencies?: string[];
|
|
5
|
+
project?: string[];
|
|
6
|
+
vitest?: true | { config: string[] };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const defaults = {
|
|
10
|
+
ignoreBinaries: ["knip", "oxfmt", "oxlint", "tsc", "vitest"],
|
|
11
|
+
ignoreDependencies: [
|
|
12
|
+
"oxfmt",
|
|
13
|
+
"oxlint",
|
|
14
|
+
"vitest",
|
|
15
|
+
"@vitest/coverage-v8",
|
|
16
|
+
"pino-pretty",
|
|
17
|
+
],
|
|
18
|
+
oxfmt: true as const,
|
|
19
|
+
oxlint: true as const,
|
|
20
|
+
project: ["src/**/*.{js,ts,tsx}", "tests/**/*.{js,ts,tsx}"],
|
|
21
|
+
typescript: true as const,
|
|
22
|
+
vitest: true as const,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export function createKnipConfig({
|
|
26
|
+
entry = [],
|
|
27
|
+
ignoreBinaries = [],
|
|
28
|
+
ignoreDependencies = [],
|
|
29
|
+
project = [],
|
|
30
|
+
...overrides
|
|
31
|
+
}: KnipConfigOverrides = {}) {
|
|
32
|
+
return {
|
|
33
|
+
...defaults,
|
|
34
|
+
...overrides,
|
|
35
|
+
...(entry.length > 0 ? { entry } : {}),
|
|
36
|
+
ignoreBinaries: [...defaults.ignoreBinaries, ...ignoreBinaries],
|
|
37
|
+
ignoreDependencies: [...defaults.ignoreDependencies, ...ignoreDependencies],
|
|
38
|
+
project: [...defaults.project, ...project],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* oxfmt has no `extends` mechanism, so unlike oxlint.ts this is a plain object each
|
|
3
|
+
* app's oxfmt.config.ts spreads into its own `defineConfig({...})` call.
|
|
4
|
+
*/
|
|
5
|
+
export const baseOxfmtConfig = {
|
|
6
|
+
printWidth: 100,
|
|
7
|
+
sortImports: { newlinesBetween: false },
|
|
8
|
+
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { defineConfig } from "oxlint";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Ignore patterns shared by every app, for both oxlint and oxfmt (see oxfmt.ts).
|
|
5
|
+
* oxlint's `extends` merges `rules`, `plugins`, `jsPlugins`, `overrides` and
|
|
6
|
+
* `options` from extended configs (last one wins on conflicting keys), but NOT
|
|
7
|
+
* `ignorePatterns` — that field is fully replaced by whichever config sets it
|
|
8
|
+
* last, so each app spreads this array into its own instead of relying on
|
|
9
|
+
* `extends` for it.
|
|
10
|
+
*/
|
|
11
|
+
export const baseIgnorePatterns = [
|
|
12
|
+
"public/**",
|
|
13
|
+
"dist/**",
|
|
14
|
+
"coverage/**",
|
|
15
|
+
"node_modules/**",
|
|
16
|
+
"tests/files/**",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export default defineConfig({
|
|
20
|
+
jsPlugins: [
|
|
21
|
+
"eslint-plugin-sonarjs",
|
|
22
|
+
"eslint-plugin-perfectionist",
|
|
23
|
+
"eslint-plugin-security",
|
|
24
|
+
"eslint-plugin-regexp",
|
|
25
|
+
],
|
|
26
|
+
options: {
|
|
27
|
+
typeAware: true,
|
|
28
|
+
typeCheck: true,
|
|
29
|
+
},
|
|
30
|
+
plugins: [
|
|
31
|
+
"unicorn",
|
|
32
|
+
"typescript",
|
|
33
|
+
"oxc",
|
|
34
|
+
"import",
|
|
35
|
+
"promise",
|
|
36
|
+
"jsdoc",
|
|
37
|
+
"node",
|
|
38
|
+
"vitest",
|
|
39
|
+
],
|
|
40
|
+
rules: {
|
|
41
|
+
"perfectionist/sort-array-includes": [
|
|
42
|
+
"warn",
|
|
43
|
+
{ order: "asc", type: "natural" },
|
|
44
|
+
],
|
|
45
|
+
"perfectionist/sort-classes": ["warn", { order: "asc", type: "natural" }],
|
|
46
|
+
"perfectionist/sort-decorators": [
|
|
47
|
+
"warn",
|
|
48
|
+
{ order: "asc", type: "natural" },
|
|
49
|
+
],
|
|
50
|
+
"perfectionist/sort-enums": ["warn", { order: "asc", type: "natural" }],
|
|
51
|
+
"perfectionist/sort-export-attributes": [
|
|
52
|
+
"warn",
|
|
53
|
+
{ order: "asc", type: "natural" },
|
|
54
|
+
],
|
|
55
|
+
"perfectionist/sort-exports": ["warn", { order: "asc", type: "natural" }],
|
|
56
|
+
"perfectionist/sort-heritage-clauses": [
|
|
57
|
+
"warn",
|
|
58
|
+
{ order: "asc", type: "natural" },
|
|
59
|
+
],
|
|
60
|
+
"perfectionist/sort-import-attributes": [
|
|
61
|
+
"warn",
|
|
62
|
+
{ order: "asc", type: "natural" },
|
|
63
|
+
],
|
|
64
|
+
"perfectionist/sort-interfaces": [
|
|
65
|
+
"warn",
|
|
66
|
+
{ order: "asc", type: "natural" },
|
|
67
|
+
],
|
|
68
|
+
"perfectionist/sort-intersection-types": [
|
|
69
|
+
"warn",
|
|
70
|
+
{ order: "asc", type: "natural" },
|
|
71
|
+
],
|
|
72
|
+
"perfectionist/sort-jsx-props": ["warn", { order: "asc", type: "natural" }],
|
|
73
|
+
"perfectionist/sort-maps": ["warn", { order: "asc", type: "natural" }],
|
|
74
|
+
"perfectionist/sort-modules": ["warn", { order: "asc", type: "natural" }],
|
|
75
|
+
"perfectionist/sort-named-exports": [
|
|
76
|
+
"warn",
|
|
77
|
+
{ order: "asc", type: "natural" },
|
|
78
|
+
],
|
|
79
|
+
"perfectionist/sort-named-imports": [
|
|
80
|
+
"warn",
|
|
81
|
+
{ order: "asc", type: "natural" },
|
|
82
|
+
],
|
|
83
|
+
"perfectionist/sort-object-types": [
|
|
84
|
+
"warn",
|
|
85
|
+
{ order: "asc", type: "natural" },
|
|
86
|
+
],
|
|
87
|
+
"perfectionist/sort-objects": ["warn", { order: "asc", type: "natural" }],
|
|
88
|
+
"perfectionist/sort-sets": ["warn", { order: "asc", type: "natural" }],
|
|
89
|
+
"perfectionist/sort-switch-case": [
|
|
90
|
+
"warn",
|
|
91
|
+
{ order: "asc", type: "natural" },
|
|
92
|
+
],
|
|
93
|
+
"perfectionist/sort-union-types": [
|
|
94
|
+
"warn",
|
|
95
|
+
{ order: "asc", type: "natural" },
|
|
96
|
+
],
|
|
97
|
+
"perfectionist/sort-variable-declarations": [
|
|
98
|
+
"warn",
|
|
99
|
+
{ order: "asc", type: "natural" },
|
|
100
|
+
],
|
|
101
|
+
|
|
102
|
+
"regexp/no-super-linear-backtracking": "warn",
|
|
103
|
+
"regexp/no-unused-capturing-group": "warn",
|
|
104
|
+
"regexp/prefer-regexp-test": "warn",
|
|
105
|
+
|
|
106
|
+
"security/detect-bidi-characters": "error",
|
|
107
|
+
"security/detect-child-process": "warn",
|
|
108
|
+
"security/detect-eval-with-expression": "error",
|
|
109
|
+
"security/detect-new-buffer": "error",
|
|
110
|
+
"security/detect-non-literal-fs-filename": "warn",
|
|
111
|
+
"security/detect-non-literal-regexp": "warn",
|
|
112
|
+
"security/detect-unsafe-regex": "warn",
|
|
113
|
+
|
|
114
|
+
"sonarjs/cognitive-complexity": "warn",
|
|
115
|
+
"sonarjs/max-switch-cases": ["warn", 30],
|
|
116
|
+
"sonarjs/no-all-duplicated-branches": "warn",
|
|
117
|
+
"sonarjs/no-collapsible-if": "warn",
|
|
118
|
+
"sonarjs/no-collection-size-mischeck": "warn",
|
|
119
|
+
"sonarjs/no-duplicate-string": ["warn", { threshold: 5 }],
|
|
120
|
+
"sonarjs/no-duplicated-branches": "warn",
|
|
121
|
+
"sonarjs/no-element-overwrite": "warn",
|
|
122
|
+
"sonarjs/no-empty-collection": "warn",
|
|
123
|
+
"sonarjs/no-extra-arguments": "warn",
|
|
124
|
+
"sonarjs/no-identical-conditions": "warn",
|
|
125
|
+
"sonarjs/no-identical-expressions": "warn",
|
|
126
|
+
"sonarjs/no-identical-functions": "warn",
|
|
127
|
+
"sonarjs/no-redundant-boolean": "warn",
|
|
128
|
+
"sonarjs/no-small-switch": "warn",
|
|
129
|
+
"sonarjs/no-unused-collection": "warn",
|
|
130
|
+
"sonarjs/no-use-of-empty-return-value": "warn",
|
|
131
|
+
"sonarjs/no-useless-catch": "warn",
|
|
132
|
+
"sonarjs/prefer-immediate-return": "warn",
|
|
133
|
+
"sonarjs/prefer-read-only-props": "warn",
|
|
134
|
+
"sonarjs/prefer-single-boolean-return": "warn",
|
|
135
|
+
},
|
|
136
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nexst/queues",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./src/index.ts"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"lint": "oxlint",
|
|
10
|
+
"lint:fix": "oxlint --fix",
|
|
11
|
+
"fmt": "oxfmt",
|
|
12
|
+
"fmt:check": "oxfmt --check",
|
|
13
|
+
"lint:ts": "tsc --noEmit"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Payload apps/api enqueues on `EXAMPLE_QUEUE`. */
|
|
2
|
+
export type ExampleJob = {
|
|
3
|
+
message: string;
|
|
4
|
+
requestedAt: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
/** What apps/worker returns once an `ExampleJob` is processed. */
|
|
8
|
+
export type ExampleJobResult = {
|
|
9
|
+
processedAt: string;
|
|
10
|
+
reversed: string;
|
|
11
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type RedisConnectionOptions = {
|
|
2
|
+
host: string;
|
|
3
|
+
maxRetriesPerRequest: null;
|
|
4
|
+
port: number;
|
|
5
|
+
retryStrategy: (times: number) => null | number;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Shared ioredis connection options for the BullMQ producer (apps/api) and
|
|
10
|
+
* consumer (apps/worker) sides of every queue in this package. `maxRetriesPerRequest:
|
|
11
|
+
* null` is required by BullMQ; the capped exponential retry strategy keeps
|
|
12
|
+
* both sides behaving the same way during a Redis outage.
|
|
13
|
+
*/
|
|
14
|
+
export function createRedisConnectionOptions(config: {
|
|
15
|
+
host: string;
|
|
16
|
+
port: number;
|
|
17
|
+
retryLimit?: number;
|
|
18
|
+
}): RedisConnectionOptions {
|
|
19
|
+
const retryLimit = config.retryLimit ?? 5;
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
host: config.host,
|
|
23
|
+
maxRetriesPerRequest: null,
|
|
24
|
+
port: config.port,
|
|
25
|
+
retryStrategy: (times: number) => (times > retryLimit ? null : Math.min(times * 100, 2000)),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"strict": true,
|
|
6
|
+
"noUnusedLocals": true,
|
|
7
|
+
"noUnusedParameters": true,
|
|
8
|
+
"noImplicitOverride": true,
|
|
9
|
+
"noFallthroughCasesInSwitch": true,
|
|
10
|
+
"noUncheckedSideEffectImports": true,
|
|
11
|
+
"allowUnreachableCode": false,
|
|
12
|
+
"allowUnusedLabels": false,
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"isolatedModules": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"skipLibCheck": true,
|
|
17
|
+
"forceConsistentCasingInFileNames": true,
|
|
18
|
+
"noEmit": true,
|
|
19
|
+
"incremental": true,
|
|
20
|
+
"sourceMap": true,
|
|
21
|
+
"removeComments": true
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"extends": "./base.json",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"module": "nodenext",
|
|
6
|
+
"moduleResolution": "nodenext",
|
|
7
|
+
"resolvePackageJsonExports": true,
|
|
8
|
+
"verbatimModuleSyntax": true,
|
|
9
|
+
"lib": ["ESNext"]
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://turborepo.com/schema.json",
|
|
3
|
+
"tasks": {
|
|
4
|
+
"transit": {
|
|
5
|
+
"dependsOn": ["^transit"]
|
|
6
|
+
},
|
|
7
|
+
"dev": {
|
|
8
|
+
"cache": false,
|
|
9
|
+
"persistent": true
|
|
10
|
+
},
|
|
11
|
+
"build": {
|
|
12
|
+
"dependsOn": ["transit"],
|
|
13
|
+
"outputs": [
|
|
14
|
+
".next/**",
|
|
15
|
+
"!.next/cache/**"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"lint": {
|
|
19
|
+
"dependsOn": ["transit"],
|
|
20
|
+
"outputs": []
|
|
21
|
+
},
|
|
22
|
+
"lint:fix": {
|
|
23
|
+
"dependsOn": ["transit"],
|
|
24
|
+
"outputs": []
|
|
25
|
+
},
|
|
26
|
+
"lint:ts": {
|
|
27
|
+
"dependsOn": ["transit"],
|
|
28
|
+
"outputs": []
|
|
29
|
+
},
|
|
30
|
+
"fmt": {
|
|
31
|
+
"dependsOn": ["transit"],
|
|
32
|
+
"outputs": [],
|
|
33
|
+
"cache": false
|
|
34
|
+
},
|
|
35
|
+
"fmt:check": {
|
|
36
|
+
"dependsOn": ["transit"],
|
|
37
|
+
"outputs": []
|
|
38
|
+
},
|
|
39
|
+
"unused": {
|
|
40
|
+
"dependsOn": ["transit"],
|
|
41
|
+
"outputs": []
|
|
42
|
+
},
|
|
43
|
+
"test:unit": {
|
|
44
|
+
"dependsOn": ["transit"],
|
|
45
|
+
"outputs": [
|
|
46
|
+
"coverage/**"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|