@percepta/create 3.6.2 → 4.0.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.
Files changed (117) hide show
  1. package/README.md +37 -6
  2. package/dist/{git-ops-C2CIjuce.js → git-ops-BD7JNnal.js} +1 -1
  3. package/dist/{git-ops-C2CIjuce.js.map → git-ops-BD7JNnal.js.map} +1 -1
  4. package/dist/github-RCIMUq70.js +131 -0
  5. package/dist/github-RCIMUq70.js.map +1 -0
  6. package/dist/index.js +68 -125
  7. package/dist/index.js.map +1 -1
  8. package/dist/{init-sI9aIrkU.js → init-COp0nGdk.js} +4 -2
  9. package/dist/{init-sI9aIrkU.js.map → init-COp0nGdk.js.map} +1 -1
  10. package/dist/manifest-CqIDnbgs.js +58 -0
  11. package/dist/manifest-CqIDnbgs.js.map +1 -0
  12. package/dist/register-app-C7ZBpAaZ.js +103 -0
  13. package/dist/register-app-C7ZBpAaZ.js.map +1 -0
  14. package/dist/register-os-blueprint-DGjBUZYa.js +90 -0
  15. package/dist/register-os-blueprint-DGjBUZYa.js.map +1 -0
  16. package/dist/{status-CKe4aKso.js → status-BXYaQ4a2.js} +3 -3
  17. package/dist/{status-CKe4aKso.js.map → status-BXYaQ4a2.js.map} +1 -1
  18. package/dist/{sync-D1vkoofl.js → sync-BayU4w1j.js} +3 -3
  19. package/dist/{sync-D1vkoofl.js.map → sync-BayU4w1j.js.map} +1 -1
  20. package/dist/template-versions-CEIP9vhl.js +35 -0
  21. package/dist/template-versions-CEIP9vhl.js.map +1 -0
  22. package/dist/{upstream-gUHLWSR1.js → upstream-CZEzLrS4.js} +3 -3
  23. package/dist/{upstream-gUHLWSR1.js.map → upstream-CZEzLrS4.js.map} +1 -1
  24. package/dist/validate-dssldJAj.js +14 -0
  25. package/dist/validate-dssldJAj.js.map +1 -0
  26. package/package.json +1 -1
  27. package/template-versions.json +2 -2
  28. package/templates/infra/os.blueprint.yaml.template +138 -0
  29. package/templates/library/README.md +5 -2
  30. package/templates/library/gitignore.template +1 -0
  31. package/templates/library/package.json.template +17 -13
  32. package/templates/library/src/index.test.ts +8 -0
  33. package/templates/library/tsconfig.json +1 -17
  34. package/templates/library/tsdown.config.ts +3 -0
  35. package/templates/library/vitest.config.ts +3 -0
  36. package/templates/monorepo/.dockerignore +1 -0
  37. package/templates/monorepo/.github/CODEOWNERS +67 -0
  38. package/templates/monorepo/.github/actions/ci/action.yml +56 -0
  39. package/templates/monorepo/.github/workflows/build-and-publish.yml +22 -0
  40. package/templates/monorepo/.github/workflows/pr-build.yml +21 -0
  41. package/templates/monorepo/.node-version +1 -0
  42. package/templates/monorepo/README.md +41 -3
  43. package/templates/monorepo/auth/README.md +6 -3
  44. package/templates/monorepo/auth/package.json +5 -7
  45. package/templates/monorepo/auth/src/auth.ts +0 -1
  46. package/templates/monorepo/auth/src/config/database.ts +1 -1
  47. package/templates/monorepo/auth/tsconfig.json +1 -10
  48. package/templates/{webapp → monorepo}/docker-compose.yml +2 -2
  49. package/templates/monorepo/gitignore.template +1 -0
  50. package/templates/monorepo/oxfmt.config.ts.template +3 -0
  51. package/templates/monorepo/oxlint.config.ts.template +3 -0
  52. package/templates/monorepo/package.json.template +22 -11
  53. package/templates/monorepo/scripts/setup-local-databases.mjs +183 -0
  54. package/templates/monorepo/turbo.json +20 -0
  55. package/templates/webapp/.node-version +0 -1
  56. package/templates/webapp/AGENTS.md +33 -35
  57. package/templates/webapp/README.md +34 -38
  58. package/templates/webapp/agent-skills/database.md +21 -21
  59. package/templates/webapp/agent-skills/langfuse.md +7 -7
  60. package/templates/webapp/agent-skills/llm.md +4 -2
  61. package/templates/webapp/agent-skills/oneshot.md +7 -6
  62. package/templates/webapp/agent-skills/ryvn.md +12 -16
  63. package/templates/webapp/deploy/README.md +10 -51
  64. package/templates/webapp/drizzle.config.ts +2 -23
  65. package/templates/webapp/env.example.template +8 -14
  66. package/templates/webapp/globals.d.ts +1 -0
  67. package/templates/webapp/oxfmt.config.ts.template +5 -0
  68. package/templates/webapp/package.json.template +18 -33
  69. package/templates/webapp/scripts/seed.ts +1 -1
  70. package/templates/webapp/scripts/start.sh +12 -16
  71. package/templates/webapp/src/app/global-error.tsx +1 -1
  72. package/templates/webapp/src/config/getEnvConfig.ts +4 -10
  73. package/templates/webapp/src/config/isDev.ts +0 -2
  74. package/templates/webapp/src/drizzle/db.ts +6 -21
  75. package/templates/webapp/src/lib/auth-client.ts +6 -3
  76. package/templates/webapp/src/startup-checks.ts +28 -7
  77. package/templates/webapp/tsconfig.json +1 -12
  78. package/templates/webapp/vitest.config.ts +3 -7
  79. package/templates/library/eslint.config.js +0 -10
  80. package/templates/monorepo/auth/scripts/setup-database.ts +0 -11
  81. package/templates/monorepo/eslint.config.js +0 -10
  82. package/templates/monorepo/tsconfig.json +0 -16
  83. package/templates/webapp/.github/workflows/__APP_NAME__-terraform-ryvn-release.yaml +0 -92
  84. package/templates/webapp/.github/workflows/ci.yml +0 -149
  85. package/templates/webapp/.prettierrc.mjs +0 -5
  86. package/templates/webapp/agent-skills/deploy.md +0 -92
  87. package/templates/webapp/deploy/ryvn/__APP_NAME__-terraform.service.yaml +0 -10
  88. package/templates/webapp/deploy/ryvn/environments/percepta-test/installations/__APP_NAME__-terraform.env.percepta-test.serviceinstallation.yaml +0 -11
  89. package/templates/webapp/deploy/ryvn/environments/percepta-test/installations/__APP_NAME__.env.percepta-test.serviceinstallation.yaml +0 -154
  90. package/templates/webapp/eslint.config.mjs +0 -100
  91. package/templates/webapp/npmrc.template +0 -4
  92. package/templates/webapp/terraform/README.md +0 -147
  93. package/templates/webapp/terraform/deploy.sh +0 -97
  94. package/templates/webapp/terraform/main.tf +0 -101
  95. package/templates/webapp/terraform/modules/cloudtrail/main.tf +0 -27
  96. package/templates/webapp/terraform/modules/cloudtrail/outputs.tf +0 -10
  97. package/templates/webapp/terraform/modules/cloudtrail/variables.tf +0 -15
  98. package/templates/webapp/terraform/modules/networking/main.tf +0 -118
  99. package/templates/webapp/terraform/modules/networking/outputs.tf +0 -38
  100. package/templates/webapp/terraform/modules/networking/variables.tf +0 -24
  101. package/templates/webapp/terraform/modules/rds/main.tf +0 -227
  102. package/templates/webapp/terraform/modules/rds/outputs.tf +0 -73
  103. package/templates/webapp/terraform/modules/rds/variables.tf +0 -61
  104. package/templates/webapp/terraform/modules/s3-logging/main.tf +0 -148
  105. package/templates/webapp/terraform/modules/s3-logging/outputs.tf +0 -10
  106. package/templates/webapp/terraform/modules/s3-logging/variables.tf +0 -16
  107. package/templates/webapp/terraform/modules/secrets/main.tf +0 -39
  108. package/templates/webapp/terraform/modules/secrets/outputs.tf +0 -9
  109. package/templates/webapp/terraform/modules/secrets/variables.tf +0 -51
  110. package/templates/webapp/terraform/outputs.tf +0 -102
  111. package/templates/webapp/terraform/providers.tf +0 -32
  112. package/templates/webapp/terraform/schema/main.tf +0 -4
  113. package/templates/webapp/terraform/schema/outputs.tf +0 -9
  114. package/templates/webapp/terraform/schema/variables.tf +0 -19
  115. package/templates/webapp/terraform/schema/versions.tf +0 -38
  116. package/templates/webapp/terraform/terraform.tfvars.example +0 -65
  117. package/templates/webapp/terraform/variables.tf +0 -129
@@ -142,8 +142,7 @@ Once all chunks are implemented, verify the app runs end-to-end locally.
142
142
  ### Step 1: Start dependencies
143
143
 
144
144
  ```bash
145
- pnpm docker:up
146
- pnpm db:setup-and-migrate
145
+ pnpm run setup
147
146
  ```
148
147
 
149
148
  If the app uses Inngest functions, start the local Inngest dev server in a separate terminal:
@@ -192,19 +191,21 @@ git init
192
191
  git add -A
193
192
  git commit -m "Initial implementation of <app-name>"
194
193
 
195
- # Create the repo under the Percepta-Core org
196
- gh repo create Percepta-Core/<app-name> --internal --source=. --push
194
+ # Create and push the repo in the target GitHub org
195
+ gh repo create <org>/<app-name> --internal --source=. --push
197
196
  ```
198
197
 
199
198
  If `gh` is not authenticated, tell the user to run `gh auth login` and then continue.
200
199
 
201
200
  ---
202
201
 
203
- ## Phase 6: Deploy to Ryvn (When Requested)
202
+ ## Phase 6: Deploy (When Requested)
204
203
 
205
204
  Only do this when the user explicitly asks to deploy.
206
205
 
207
- Follow the step-by-step guide in [agent-skills/deploy.md](deploy.md). It contains the service definition, installation YAML, environment variables, and secrets needed for percepta-test.
206
+ Deployment is stack-specific. Confirm the target environment and use the
207
+ customer infra repo or deployment guide for that stack. Blueberry does not
208
+ generate environment-specific installation YAML.
208
209
 
209
210
  For Ryvn CLI operations (checking status, logs, troubleshooting), use the `/use-ryvn` skill.
210
211
 
@@ -1,25 +1,21 @@
1
- # Ryvn — Deployment Platform
1
+ # Ryvn
2
2
 
3
- Ryvn is the deployment platform used by Percepta to manage cloud infrastructure. It provisions environments, deploys services, and handles CI/CD abstracting away Kubernetes, Terraform, and cloud provider details.
3
+ Ryvn can be used to register and release this app as a service. Blueberry does
4
+ not generate a target environment installation because those details are
5
+ customer and stack specific.
4
6
 
5
- ## Percepta Environments
7
+ ## Generated Files
6
8
 
7
- | Environment | Purpose | Domain pattern |
8
- |-------------|---------|---------------|
9
- | `percepta-test` | Internal dev/test | `<app>.percepta-test.aitco.dev` |
9
+ - `deploy/ryvn/__APP_NAME__.service.yaml` declares the app service and Docker build context.
10
+ - `.github/workflows/__APP_NAME__-ryvn-release.yaml` builds the image and creates a Ryvn release.
10
11
 
11
- New apps are deployed to **percepta-test** using the existing-environment deploy motion. This environment must already have shared PostgreSQL, Inngest, OTEL collector, LGTM stack, and Langfuse installations before app deploys run. The service installation points at the shared Langfuse URL and attaches the `demos-commons` variable group for shared demo Langfuse project keys.
12
+ ## Environment Installations
12
13
 
13
- ## Deploying This App
14
-
15
- For the full step-by-step deployment guide to percepta-test, see [deploy.md](deploy.md).
14
+ Environment installations belong in the infra repo. A customer blueprint should
15
+ compose the required base infrastructure, monorepo infrastructure, app database
16
+ registration, runtime services, ingress, secrets, and the app service
17
+ installation for the target stack.
16
18
 
17
19
  ## Ryvn CLI
18
20
 
19
21
  For all Ryvn CLI operations (checking status, viewing logs, troubleshooting, managing installations), use the **`/use-ryvn`** skill. It has comprehensive CLI reference docs and handles authentication, deployment, configuration, and operations.
20
-
21
- ```bash
22
- # Quick status check
23
- ryvn get installation __APP_NAME__ -e percepta-test
24
- ryvn logs __APP_NAME__ -e percepta-test
25
- ```
@@ -1,66 +1,25 @@
1
1
  # Deploy
2
2
 
3
- This directory holds Ryvn infrastructure-as-code for deploying __APP_TITLE__ to Percepta environments.
3
+ This directory contains environment-neutral deployment metadata for __APP_TITLE__.
4
+ It intentionally does not include customer or environment installation files.
4
5
 
5
6
  ```
6
7
  deploy/
7
8
  └── ryvn/
8
- ├── __APP_NAME__.service.yaml
9
- ├── __APP_NAME__-terraform.service.yaml
10
- └── environments/
11
- └── percepta-test/
12
- └── installations/
13
- ├── __APP_NAME__.env.percepta-test.serviceinstallation.yaml
14
- └── __APP_NAME__-terraform.env.percepta-test.serviceinstallation.yaml
9
+ └── __APP_NAME__.service.yaml
15
10
  ```
16
11
 
17
- These files deploy to `https://__APP_NAME__.percepta-test.aitco.dev`.
18
-
19
- The default deploy helper performs the existing-environment deploy motion: it assumes the target Ryvn environment already has the shared platform services installed, then wires this app into them. For `percepta-test`, that means shared Postgres, Inngest, the OTEL collector, the LGTM stack, and Langfuse must already exist before app deploy starts. Fresh-environment platform bootstrap is a separate motion and should be handled by a Ryvn blueprint or environment-specific platform rollout.
20
-
21
- The `pnpm deploy:percepta-test` script delegates to the versioned `@percepta/deploy` CLI. The app owns only the Ryvn service/installation YAML and secrets env file. The helper talks directly to Ryvn: it preflights the existing platform services, creates/updates the services, runs the GitHub Actions release workflows, creates the schema installation, approves the schema Terraform plan, creates or updates app-scoped Ryvn secrets, creates the web installation, waits for health, and verifies the health and app routes.
22
-
23
- ## Deploying
24
-
25
- Tell Claude "deploy this app to percepta-test" or run:
26
-
27
- ```bash
28
- pnpm deploy:percepta-test -- --yes
29
- ```
30
-
31
- The helper expects a clean, committed git worktree because GitHub Actions builds from the pushed repo. It can create `Percepta-Core/__REPO_NAME__` if it does not exist yet, and it pushes the current branch to `main` before triggering releases.
12
+ The generated app owns its buildable service identity. The infra repo owns
13
+ customer blueprints, environment installations, app database registration,
14
+ runtime dependencies, ingress, secrets, and rollout policy.
32
15
 
33
16
  ## What's in these files
34
17
 
35
18
  **`__APP_NAME__.service.yaml`** — Ryvn server service for the web app. It points at `Percepta-Core/__REPO_NAME__` and builds from `packages/__APP_NAME__/`.
36
19
 
37
- **`__APP_NAME__-terraform.service.yaml`** — Ryvn Terraform service that owns the per-app Postgres schema in the shared `demos` database.
38
-
39
- **`__APP_NAME__.env.percepta-test.serviceinstallation.yaml`** — web app installation for `percepta-test`. It wires the shared platform services, ingress, health probes, database connection, Inngest, OTEL/LGTM telemetry, the Langfuse base URL, and the shared demo variable group.
40
-
41
- **`__APP_NAME__-terraform.env.percepta-test.serviceinstallation.yaml`** — schema installation for `percepta-test`.
42
-
43
- **`percepta-test.secrets.env`** — generated locally and ignored by git. The deploy helper injects app-specific auth/encryption secrets into the Ryvn installation create manifest so the first pod starts with auth configured; shared Langfuse and LLM demo keys are inherited from a Ryvn variable group.
44
-
45
- ## Platform Wiring
46
-
47
- `pnpm deploy:percepta-test` checks these existing `percepta-test` installations before it mutates GitHub or Ryvn app resources:
48
-
49
- - `percepta-internal-terraform` for the shared Postgres instance.
50
- - `inngest-test` for background jobs and function callbacks.
51
- - `otel-collector` for trace, metric, and log collection.
52
- - `lgtm-stack-helm` for Loki, Grafana, Tempo, and Mimir.
53
- - `langfuse` for LLM tracing and eval observability.
54
- - `demos-commons` variable group for shared demo configuration, including the Anthropic API key and Langfuse demo project keys.
55
-
56
- The service installation sets `LANGFUSE_BASE_URL` to the shared `percepta-test` Langfuse URL, sets `LLM_PROVIDER=anthropic`, and attaches `demos-commons` for `ANTHROPIC_API_KEY`, `LANGFUSE_PUBLIC_KEY`, and sensitive `LANGFUSE_SECRET_KEY`. Individual demo apps do not need LLM or Langfuse keys in `percepta-test.secrets.env`.
57
-
58
20
  ## Notes
59
21
 
60
- The release workflows live at the repo root under `.github/workflows/`. The web workflow uses the org-level `NPM_TOKEN` secret for private `@percepta/*` packages; do not add a repo-level token unless the org secret is unavailable.
61
-
62
- For the old GitOps PR path, use `pnpm deploy:percepta-test:pr -- --phase service --yes` and then `pnpm deploy:percepta-test:pr -- --phase installation --yes`.
63
-
64
- ## Adding More Environments
65
-
66
- Copy the two `percepta-test` installation manifests to `environments/<env>/installations/`, then change the `environment:`, host, and environment-specific config.
22
+ The release workflow lives at the repo root under `.github/workflows/` after
23
+ scaffolding. It creates a Ryvn service release from the current app image.
24
+ Installing that release into any environment is a customer/stack-specific
25
+ infra concern and should be modeled in the infra repo.
@@ -1,5 +1,4 @@
1
1
  import * as nextEnvModule from "@next/env";
2
- import { getPgSearchPathOption } from "@percepta/database";
3
2
  import type { Config } from "drizzle-kit";
4
3
  import { getEnvConfig } from "./src/config/getEnvConfig";
5
4
 
@@ -9,34 +8,14 @@ const nextEnv =
9
8
 
10
9
  nextEnv.loadEnvConfig(process.cwd());
11
10
 
12
- const {
13
- DATABASE_HOST: host,
14
- DATABASE_PORT: port,
15
- DATABASE_USERNAME: user,
16
- DATABASE_PASSWORD: password,
17
- DATABASE_NAME: database,
18
- DATABASE_SCHEMA: databaseSchema,
19
- DATABASE_USE_SSL: useSSL,
20
- } = getEnvConfig();
21
-
22
- const schemaFilter = databaseSchema?.trim() || undefined;
23
- const searchPathOption = getPgSearchPathOption(schemaFilter);
24
- const connectionParams = new URLSearchParams();
25
- if (useSSL) connectionParams.set("sslmode", "require");
26
- if (searchPathOption) connectionParams.set("options", searchPathOption);
27
-
28
- const connectionString =
29
- `postgresql://${encodeURIComponent(user)}:${encodeURIComponent(password)}` +
30
- `@${host}:${port}/${encodeURIComponent(database)}` +
31
- (connectionParams.size > 0 ? `?${connectionParams.toString()}` : "");
11
+ const { DATABASE_URL: databaseUrl } = getEnvConfig();
32
12
 
33
13
  const config: Config = {
34
14
  schema: "./src/drizzle/schema",
35
15
  out: "./src/drizzle/migrations",
36
16
  dialect: "postgresql",
37
- ...(schemaFilter ? { schemaFilter: [schemaFilter] } : {}),
38
17
  dbCredentials: {
39
- url: connectionString,
18
+ url: databaseUrl,
40
19
  },
41
20
  };
42
21
 
@@ -2,21 +2,16 @@
2
2
  NODE_ENV=development
3
3
  APP_BASE_URL=http://localhost:3000
4
4
 
5
- # Database
6
- DATABASE_HOST=localhost
7
- DATABASE_PORT=5434
8
- DATABASE_USERNAME=postgres
9
- DATABASE_PASSWORD=postgres
10
- DATABASE_NAME=__DB_NAME__
11
- # DATABASE_SCHEMA=
12
- DATABASE_USE_SSL=false
5
+ # App Database
6
+ DATABASE_URL=postgresql://postgres:postgres@localhost:5434/__DB_NAME__
13
7
 
14
8
  # Authentication (Better Auth)
15
9
  BETTER_AUTH_SECRET=generate-with-openssl-rand-base64-32
16
10
  BETTER_AUTH_URL=http://localhost:3000
17
- # Optional override for the shared customer auth database. Defaults to the
18
- # customer monorepo database generated in ../../auth.
19
- # AUTH_DATABASE_NAME=
11
+
12
+ # Shared Auth Database
13
+ # Deployed apps should set this from the customer monorepo auth database Secret.
14
+ # Local development can leave it empty and use the shared auth package defaults.
20
15
  # AUTH_DATABASE_URL=
21
16
 
22
17
  # Security
@@ -46,9 +41,8 @@ NEXT_PUBLIC_FARO_APP_ENVIRONMENT=development
46
41
  # LANGFUSE_SECRET_KEY=
47
42
 
48
43
  # LLM providers
49
- # Deployed percepta-test apps inherit ANTHROPIC_API_KEY from the demos-commons
50
- # Ryvn variable group. For local LLM testing, set ANTHROPIC_API_KEY once in your
51
- # shell profile or ~/.config/percepta/create.env.
44
+ # For local LLM testing, set ANTHROPIC_API_KEY once in your shell profile or
45
+ # ~/.config/percepta/create.env.
52
46
  # ANTHROPIC_API_KEY=
53
47
  # OPENAI_API_KEY=
54
48
  # LLM_PROVIDER=anthropic
@@ -0,0 +1 @@
1
+ declare module "*.css";
@@ -0,0 +1,5 @@
1
+ import { defineOxfmtReactConfig } from "@percepta/build/oxfmt";
2
+
3
+ export default defineOxfmtReactConfig({
4
+ stylesheet: "./src/styles/globals.css",
5
+ });
@@ -2,6 +2,7 @@
2
2
  "name": "__APP_NAME__",
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
+ "type": "module",
5
6
  "engines": {
6
7
  "node": ">=18.0.0"
7
8
  },
@@ -9,23 +10,17 @@
9
10
  "dev": "tsx ./scripts/with-local-env.ts next dev --turbopack",
10
11
  "build": "next build",
11
12
  "start": "next start",
12
- "lint": "eslint .",
13
+ "typecheck": "tsc --noEmit",
13
14
  "setup": "pnpm --dir ../.. run setup",
14
- "docker:up": "docker compose up -d --wait",
15
- "docker:down": "docker compose down",
16
15
  "access:validate": "percepta-access-control validate",
17
16
  "access:apply-local": "pnpm --dir ../.. run access:apply-local",
18
- "auth:db:setup-and-migrate": "pnpm --dir ../.. run auth:db:setup-and-migrate",
17
+ "auth:db:migrate": "pnpm --dir ../.. run auth:db:migrate",
19
18
  "inngest:dev": "pnpm dlx inngest-cli@latest dev -u http://localhost:3000/api/inngest",
20
19
  "db:generate": "percepta-db generate-migrations",
21
- "db:migrate": "percepta-db migrate --database __DB_NAME__",
22
- "db:setup": "percepta-db setup --database __DB_NAME__",
23
- "db:setup-and-migrate": "pnpm db:setup && pnpm db:migrate",
24
- "db:setup-readonly": "percepta-db setup-readonly --database __DB_NAME__",
25
- "db:studio": "pnpm db:setup-and-migrate && drizzle-kit studio",
20
+ "db:migrate": "percepta-db migrate",
21
+ "db:setup-readonly": "percepta-db setup-readonly",
22
+ "db:studio": "pnpm db:migrate && drizzle-kit studio",
26
23
  "db:seed": "tsx ./scripts/seed.ts",
27
- "deploy:percepta-test": "percepta-deploy percepta-test --app __APP_NAME__ --repo __REPO_NAME__",
28
- "deploy:percepta-test:pr": "percepta-deploy percepta-test pr --app __APP_NAME__ --database-schema __APP_NAME_SNAKE__",
29
24
  "test": "vitest run",
30
25
  "test:e2e": "pnpm run setup && playwright test",
31
26
  "test:e2e:install": "playwright install chromium",
@@ -46,20 +41,20 @@
46
41
  "@grafana/faro-web-tracing": "^1.14.0",
47
42
  "@hookform/resolvers": "^5.2.2",
48
43
  "@mantine/hooks": "^8.3.1",
49
- "@next/env": "^15.3.5",
44
+ "@next/env": "^16.2.6",
50
45
  "@opentelemetry/api": "^1.9.0",
51
46
  "@opentelemetry/auto-instrumentations-node": "^0.75.0",
52
47
  "@opentelemetry/exporter-trace-otlp-proto": "^0.217.0",
53
48
  "@opentelemetry/sdk-node": "^0.217.0",
54
49
  "@__REPO_NAME__/auth": "workspace:*",
55
- "@percepta/access-control": "0.8.0",
56
- "@percepta/ai": "0.1.0",
57
- "@percepta/database": "0.1.1",
58
- "@percepta/design": "0.4.0",
59
- "@percepta/inngest": "0.1.0",
60
- "@percepta/logger": "0.1.0",
61
- "@percepta/next-utils": "0.2.1",
62
- "@percepta/utils": "0.1.10",
50
+ "@percepta/access-control": "^1.0.0",
51
+ "@percepta/ai": "^0.1.0",
52
+ "@percepta/database": "^0.1.2",
53
+ "@percepta/design": "^0.4.1",
54
+ "@percepta/inngest": "^0.1.0",
55
+ "@percepta/logger": "^0.1.0",
56
+ "@percepta/next-utils": "^0.2.2",
57
+ "@percepta/utils": "^0.1.11",
63
58
  "@radix-ui/react-slot": "^1.2.3",
64
59
  "@tanstack/react-query": "^5.81.5",
65
60
  "@tanstack/react-virtual": "^3.13.12",
@@ -79,7 +74,7 @@
79
74
  "lodash-es": "^4.17.21",
80
75
  "lucide-react": "^0.542.0",
81
76
  "mime-types": "^3.0.1",
82
- "next": "^15.3.5",
77
+ "next": "^16.2.6",
83
78
  "numeral": "^2.0.6",
84
79
  "pg": "^8.16.3",
85
80
  "pluralize": "^8.0.0",
@@ -98,11 +93,8 @@
98
93
  "zod": "^4.1.5"
99
94
  },
100
95
  "devDependencies": {
101
- "@eslint/js": "^9.18.0",
102
- "@next/eslint-plugin-next": "^15.3.5",
103
96
  "@playwright/test": "^1.58.2",
104
- "@percepta/build": "0.4.0",
105
- "@percepta/deploy": "0.1.0",
97
+ "@percepta/build": "^1.0.0",
106
98
  "@tailwindcss/postcss": "^4.1.11",
107
99
  "@types/formidable": "^3.4.5",
108
100
  "@types/he": "^1.2.3",
@@ -116,16 +108,9 @@
116
108
  "@types/react-dom": "^19.0.3",
117
109
  "@types/yargs": "^17.0.33",
118
110
  "drizzle-kit": "^0.31.4",
119
- "eslint": "^9.18.0",
120
- "eslint-plugin-n": "^17.23.1",
121
- "eslint-plugin-react": "^7.37.4",
122
- "eslint-plugin-react-hooks": "^5.2.0",
123
- "globals": "^15.14.0",
124
111
  "husky": "^9.1.7",
125
112
  "tailwindcss": "^4.0.12",
126
- "typescript": "^5.7.3",
127
- "typescript-eslint": "^8.33.0",
128
- "vitest": "^3.2.1",
113
+ "vitest": "^4.0.0",
129
114
  "yargs": "^17.7.2"
130
115
  }
131
116
  }
@@ -49,7 +49,7 @@ const SEEDED_USERS = [
49
49
 
50
50
  async function main(): Promise<void> {
51
51
  nextEnv.loadEnvConfig(process.cwd());
52
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ // oxlint-disable-next-line typescript/no-explicit-any
53
53
  (globalThis as any).AsyncLocalStorage = AsyncLocalStorage;
54
54
 
55
55
  const { auth } = await import("@__REPO_NAME__/auth");
@@ -1,24 +1,20 @@
1
- # Check if database connection variables are set
2
- if [ -z "$DATABASE_HOST" ] || [ -z "$DATABASE_USERNAME" ] || [ -z "$DATABASE_NAME" ]; then
3
- echo "⚠️ Database connection not configured. Skipping migration."
4
- echo "Required environment variables: DATABASE_HOST, DATABASE_USERNAME, DATABASE_NAME"
5
- echo "❌ Error: Missing required database environment variables."
1
+ # Check if app database connection variables are set
2
+ if [ -z "$DATABASE_URL" ]; then
3
+ echo "⚠️ App database connection not configured. Skipping migration."
4
+ echo "Required environment variable: DATABASE_URL"
5
+ echo "❌ Error: Missing required app database environment variables."
6
6
  exit 1
7
7
  else
8
- echo "Database configuration found:"
9
- echo " HOST: $DATABASE_HOST"
10
- echo " USER: $DATABASE_USERNAME"
11
- echo " DATABASE: $DATABASE_NAME"
12
- echo " SSL: ${DATABASE_USE_SSL:-false}"
8
+ echo "App database configuration found."
13
9
  fi
14
10
 
15
- # Run database migrations only if database is configured
16
- echo "Running database migrations..."
17
- if pnpm db:setup-and-migrate; then
18
- echo "✅ Database migrations completed successfully"
11
+ # Run app database migrations only if database is configured
12
+ echo "Running app database migrations..."
13
+ if pnpm db:migrate; then
14
+ echo "✅ App database migrations completed successfully"
19
15
  else
20
- echo "❌ Database migration failed. App will not start."
21
- echo "Check your database configuration and connectivity."
16
+ echo "❌ App database migration failed. App will not start."
17
+ echo "Check your app database configuration and connectivity."
22
18
  exit 1
23
19
  fi
24
20
 
@@ -8,7 +8,7 @@ export default function GlobalError({
8
8
  reset: () => void;
9
9
  }) {
10
10
  try {
11
- // eslint-disable-next-line @typescript-eslint/no-require-imports
11
+ // oxlint-disable-next-line typescript/no-require-imports
12
12
  const { faro } = require("@grafana/faro-web-sdk");
13
13
  faro.api?.pushError(error);
14
14
  } catch {
@@ -10,17 +10,10 @@ export const { getEnvConfig, schema: ENV_CONFIG_SCHEMA } = createEnvConfig(
10
10
  // Application:
11
11
  APP_BASE_URL: z.string().optional(),
12
12
 
13
- // Database:
14
- DATABASE_HOST: z.string().default("localhost"),
15
- DATABASE_PORT: z.coerce.number().int().default(5434),
16
- DATABASE_USERNAME: z.string().default("postgres"),
17
- DATABASE_PASSWORD: z.string().default("postgres"),
18
- DATABASE_NAME: z.string().default("__DB_NAME__"),
19
- DATABASE_SCHEMA: z.string().optional(),
20
- DATABASE_USE_SSL: z
13
+ // App database:
14
+ DATABASE_URL: z
21
15
  .string()
22
- .transform((value: string): boolean => value === "true")
23
- .default(false),
16
+ .default("postgresql://postgres:postgres@localhost:5434/__DB_NAME__"),
24
17
 
25
18
  // AWS:
26
19
  AWS_REGION: z.string().default("us-east-1"),
@@ -28,6 +21,7 @@ export const { getEnvConfig, schema: ENV_CONFIG_SCHEMA } = createEnvConfig(
28
21
  // Authentication (Better Auth):
29
22
  BETTER_AUTH_SECRET: z.string().optional(),
30
23
  BETTER_AUTH_URL: z.string().default("http://localhost:3000"),
24
+ AUTH_DATABASE_URL: z.string().optional(),
31
25
 
32
26
  // Inngest:
33
27
  INNGEST_BASE_URL: z.string().optional(),
@@ -1,5 +1,3 @@
1
- /* eslint-disable n/no-process-env */
2
-
3
1
  /**
4
2
  * Build-time development check. `NODE_ENV` is inlined by the bundler,
5
3
  * so this constant is safe to import in both server and client code.
@@ -1,30 +1,15 @@
1
- import { getPgSearchPathOption, getPgSslConfig } from "@percepta/database";
1
+ import { createPgPool, readDatabaseConfig } from "@percepta/database";
2
2
  import { type NodePgDatabase, drizzle } from "drizzle-orm/node-postgres";
3
- import { Pool } from "pg";
3
+ import type { Pool } from "pg";
4
4
  import { getEnvConfig } from "../config/getEnvConfig";
5
5
 
6
6
  export const { client, db } = createDb();
7
7
 
8
8
  function createDb(): { client: Pool; db: NodePgDatabase } {
9
- const {
10
- DATABASE_HOST: host,
11
- DATABASE_PORT: port,
12
- DATABASE_USERNAME: user,
13
- DATABASE_PASSWORD: password,
14
- DATABASE_NAME: database,
15
- DATABASE_SCHEMA: databaseSchema,
16
- DATABASE_USE_SSL: useSSL,
17
- } = getEnvConfig();
18
-
19
- const pool = new Pool({
20
- host,
21
- port,
22
- user,
23
- password,
24
- database,
25
- ssl: getPgSslConfig(useSSL),
26
- options: getPgSearchPathOption(databaseSchema),
27
- });
9
+ const { DATABASE_URL: databaseUrl, NODE_ENV: nodeEnv } = getEnvConfig();
10
+ const pool = createPgPool(
11
+ readDatabaseConfig({ env: { DATABASE_URL: databaseUrl, NODE_ENV: nodeEnv } }),
12
+ );
28
13
 
29
14
  return { client: pool, db: drizzle(pool) };
30
15
  }
@@ -1,6 +1,9 @@
1
+ import { BetterAuthClientOptions } from "better-auth";
1
2
  import { adminClient } from "better-auth/client/plugins";
2
3
  import { createAuthClient } from "better-auth/react";
3
4
 
4
- export const authClient = createAuthClient({
5
- plugins: [adminClient()],
6
- });
5
+ const adminPlugin: ReturnType<typeof adminClient> = adminClient();
6
+ const options = {
7
+ plugins: [adminPlugin],
8
+ } satisfies BetterAuthClientOptions;
9
+ export const authClient: ReturnType<typeof createAuthClient<typeof options>> = createAuthClient(options);
@@ -1,9 +1,14 @@
1
+ import { client as authClient } from "@__REPO_NAME__/auth/db";
1
2
  import { getEnvConfig } from "./config/getEnvConfig";
2
3
  import { client } from "./drizzle/db";
3
4
  import { getLogger } from "./services/logger/AppLogger";
4
5
 
5
6
  export async function checkStartup(): Promise<boolean> {
6
- return validateEnvironment() && (await validateDatabaseConnection());
7
+ return (
8
+ validateEnvironment() &&
9
+ (await validateDatabaseConnection()) &&
10
+ (await validateAuthDatabaseConnection())
11
+ );
7
12
  }
8
13
 
9
14
  function validateEnvironment(): boolean {
@@ -18,15 +23,31 @@ function validateEnvironment(): boolean {
18
23
 
19
24
  async function validateDatabaseConnection(): Promise<boolean> {
20
25
  try {
21
- const dbCheckPromise = client.query("SELECT 1");
22
-
23
- const timeoutPromise = new Promise((_, reject) =>
24
- setTimeout(() => reject(new Error("Database check timeout")), 5000),
25
- );
26
- await Promise.race([dbCheckPromise, timeoutPromise]);
26
+ await checkDatabaseClient(client, "Database check timeout");
27
27
  } catch {
28
28
  getLogger().warn(undefined, "Database connection failed");
29
29
  return false;
30
30
  }
31
31
  return true;
32
32
  }
33
+
34
+ async function validateAuthDatabaseConnection(): Promise<boolean> {
35
+ try {
36
+ await checkDatabaseClient(authClient, "Auth database check timeout");
37
+ } catch {
38
+ getLogger().warn(undefined, "Auth database connection failed");
39
+ return false;
40
+ }
41
+ return true;
42
+ }
43
+
44
+ async function checkDatabaseClient(
45
+ databaseClient: Pick<typeof client, "query">,
46
+ timeoutMessage: string,
47
+ ): Promise<void> {
48
+ const dbCheckPromise = databaseClient.query("SELECT 1");
49
+ const timeoutPromise = new Promise((_, reject) =>
50
+ setTimeout(() => reject(new Error(timeoutMessage)), 5000),
51
+ );
52
+ await Promise.race([dbCheckPromise, timeoutPromise]);
53
+ }
@@ -1,14 +1,3 @@
1
1
  {
2
- "extends": "@percepta/build/tsconfig/web",
3
- "compilerOptions": {
4
- "declaration": false,
5
- "declarationMap": false,
6
- "plugins": [{ "name": "next" }],
7
- "lib": ["dom", "dom.iterable", "esnext"],
8
- "allowJs": true,
9
- "noEmit": true,
10
- "isolatedModules": true,
11
- "jsx": "preserve"
12
- },
13
- "include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"]
2
+ "extends": "@percepta/build/tsconfig/web"
14
3
  }
@@ -1,9 +1,5 @@
1
- import { defineConfig } from "vitest/config";
1
+ import { createVitestConfig } from "@percepta/build/vitest";
2
2
 
3
- export default defineConfig({
4
- test: {
5
- environment: "node",
6
- include: ["src/**/__tests__/**/*.test.ts"],
7
- setupFiles: ["./vitest.setup.ts"],
8
- },
3
+ export default createVitestConfig({
4
+ additionalSetupFiles: ["./vitest.setup.ts"],
9
5
  });
@@ -1,10 +0,0 @@
1
- import eslint from "@eslint/js";
2
- import tseslint from "typescript-eslint";
3
-
4
- export default tseslint.config(
5
- eslint.configs.recommended,
6
- ...tseslint.configs.recommended,
7
- {
8
- ignores: ["node_modules/**", "dist/**"],
9
- }
10
- );
@@ -1,11 +0,0 @@
1
- import { setupAuthDatabase } from "@percepta/auth";
2
- import { getAuthDatabaseConfig } from "../src/config/database";
3
-
4
- async function main(): Promise<void> {
5
- await setupAuthDatabase({ config: getAuthDatabaseConfig() });
6
- }
7
-
8
- void main().catch((error) => {
9
- console.error("Shared auth database setup failed:", error);
10
- process.exit(1);
11
- });
@@ -1,10 +0,0 @@
1
- import eslint from "@eslint/js";
2
- import tseslint from "typescript-eslint";
3
-
4
- export default tseslint.config(
5
- eslint.configs.recommended,
6
- ...tseslint.configs.recommended,
7
- {
8
- ignores: ["**/node_modules/**", "**/dist/**"],
9
- }
10
- );
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "lib": ["ES2022"],
5
- "module": "NodeNext",
6
- "moduleResolution": "NodeNext",
7
- "strict": true,
8
- "esModuleInterop": true,
9
- "skipLibCheck": true,
10
- "forceConsistentCasingInFileNames": true,
11
- "declaration": true,
12
- "declarationMap": true,
13
- "sourceMap": true,
14
- "resolveJsonModule": true
15
- }
16
- }