create-m5kdev 0.32.8 → 0.34.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/src/catalog.cjs +76 -11
- package/dist/src/catalog.cjs.map +1 -1
- package/dist/src/catalog.d.cts +13 -1
- package/dist/src/create.cjs +6 -2
- package/dist/src/create.cjs.map +1 -1
- package/dist/src/doctor.cjs +13 -7
- package/dist/src/doctor.cjs.map +1 -1
- package/dist/src/fs.cjs +10 -5
- package/dist/src/fs.cjs.map +1 -1
- package/dist/src/prompts.cjs +32 -0
- package/dist/src/prompts.cjs.map +1 -1
- package/dist/src/prompts.d.cts +7 -1
- package/dist/src/template.cjs +23 -4
- package/dist/src/template.cjs.map +1 -1
- package/dist/src/template.d.cts +17 -3
- package/dist/src/types.d.cts +11 -4
- package/package.json +4 -1
- package/templates/minimal-app/.cursor/rules/module-dto-guide.mdc +1 -1
- package/templates/minimal-app/.cursor/rules/module-grants-guide.mdc +3 -3
- package/templates/minimal-app/.cursor/rules/module-module-guide.mdc +3 -2
- package/templates/minimal-app/.cursor/rules/module-service-guide.mdc +1 -1
- package/templates/minimal-app/.dockerignore.tpl +31 -0
- package/templates/minimal-app/.gitignore.tpl +1 -0
- package/templates/minimal-app/AGENTS.md.tpl +13 -10
- package/templates/minimal-app/CLAUDE.md.tpl +132 -131
- package/templates/minimal-app/README.md.tpl +50 -19
- package/templates/minimal-app/apps/e2e/package.json.tpl +23 -23
- package/templates/minimal-app/apps/e2e/playwright.config.ts.tpl +51 -39
- package/templates/minimal-app/apps/e2e/playwright.expo.config.ts.tpl +38 -38
- package/templates/minimal-app/apps/e2e/servers.ts.tpl +136 -112
- package/templates/minimal-app/apps/e2e/tests/conversation.spec.ts.tpl +22 -0
- package/templates/minimal-app/apps/e2e/tests/email.spec.ts.tpl +47 -47
- package/templates/minimal-app/apps/e2e/tests/expo-helpers.ts.tpl +73 -73
- package/templates/minimal-app/apps/e2e/tests/expo-standard.spec.ts.tpl +517 -517
- package/templates/minimal-app/apps/e2e/tests/expo-waitlist.spec.ts.tpl +94 -94
- package/templates/minimal-app/apps/e2e/tests/files.spec.ts.tpl +35 -0
- package/templates/minimal-app/apps/e2e/tests/helpers.ts.tpl +289 -289
- package/templates/minimal-app/apps/e2e/tests/standard.spec.ts.tpl +516 -516
- package/templates/minimal-app/apps/e2e/tests/waitlist.spec.ts.tpl +107 -107
- package/templates/minimal-app/apps/e2e/tests/workflow.spec.ts.tpl +26 -0
- package/templates/minimal-app/apps/e2e/tsconfig.json.tpl +10 -10
- package/templates/minimal-app/apps/email/package.json.tpl +34 -34
- package/templates/minimal-app/apps/email/src/emails/trialEndingEmail.tsx.tpl +40 -0
- package/templates/minimal-app/apps/email/src/index.ts.tpl +7 -0
- package/templates/minimal-app/apps/email/src/resources.ts.tpl +72 -65
- package/templates/minimal-app/apps/expo/app.json.tpl +36 -36
- package/templates/minimal-app/apps/expo/eslint.config.js.tpl +8 -8
- package/templates/minimal-app/apps/expo/metro.config.js.tpl +16 -16
- package/templates/minimal-app/apps/expo/package.json.tpl +59 -59
- package/templates/minimal-app/apps/expo/src/app/_layout.tsx.tpl +31 -31
- package/templates/minimal-app/apps/expo/src/app/claim-account.tsx.tpl +151 -151
- package/templates/minimal-app/apps/expo/src/app/forgot-password.tsx.tpl +53 -53
- package/templates/minimal-app/apps/expo/src/app/index.tsx.tpl +8 -8
- package/templates/minimal-app/apps/expo/src/app/login.tsx.tpl +71 -71
- package/templates/minimal-app/apps/expo/src/app/logout.tsx.tpl +19 -19
- package/templates/minimal-app/apps/expo/src/app/organization/accept-invitation.tsx.tpl +85 -85
- package/templates/minimal-app/apps/expo/src/app/posts.tsx.tpl +40 -40
- package/templates/minimal-app/apps/expo/src/app/reset-password.tsx.tpl +75 -75
- package/templates/minimal-app/apps/expo/src/app/signup.tsx.tpl +193 -193
- package/templates/minimal-app/apps/expo/src/components/AuthScaffold.tsx.tpl +34 -34
- package/templates/minimal-app/apps/expo/src/components/FormTextField.tsx.tpl +37 -37
- package/templates/minimal-app/apps/expo/src/components/LoadingScreen.tsx.tpl +10 -10
- package/templates/minimal-app/apps/expo/src/components/StatusText.tsx.tpl +22 -22
- package/templates/minimal-app/apps/expo/src/config.ts.tpl +9 -9
- package/templates/minimal-app/apps/expo/src/global.css.tpl +11 -11
- package/templates/minimal-app/apps/expo/src/lib/trpc.ts.tpl +20 -20
- package/templates/minimal-app/apps/expo/tsconfig.json.tpl +11 -11
- package/templates/minimal-app/apps/expo/uniwind-env.d.ts.tpl +1 -1
- package/templates/minimal-app/apps/landing/.env.production.example.tpl +7 -0
- package/templates/minimal-app/apps/landing/Dockerfile.tpl +39 -0
- package/templates/minimal-app/apps/landing/fly.toml.tpl +20 -0
- package/templates/minimal-app/apps/landing/index.html.tpl +35 -0
- package/templates/minimal-app/apps/landing/package.json.tpl +34 -0
- package/templates/minimal-app/apps/landing/scripts/fly-deploy.mjs.tpl +75 -0
- package/templates/minimal-app/apps/landing/scripts/fly-secrets.mjs.tpl +31 -0
- package/templates/minimal-app/apps/landing/src/App.tsx.tpl +12 -0
- package/templates/minimal-app/apps/landing/src/LandingPage.tsx.tpl +37 -0
- package/templates/minimal-app/apps/landing/src/index.css.tpl +24 -0
- package/templates/minimal-app/apps/landing/src/main.tsx.tpl +16 -0
- package/templates/minimal-app/apps/landing/src/vite-env.d.ts.tpl +11 -0
- package/templates/minimal-app/apps/landing/tsconfig.json.tpl +12 -0
- package/templates/minimal-app/apps/landing/vite.config.ts.tpl +25 -0
- package/templates/minimal-app/apps/server/AGENTS.md.tpl +54 -46
- package/templates/minimal-app/apps/server/{drizzle/seed.e2e.ts.tpl → db.e2e.ts.tpl} +57 -40
- package/templates/minimal-app/apps/server/{drizzle/seed.ts.tpl → db.ts.tpl} +27 -20
- package/templates/minimal-app/apps/server/drizzle/0002_concerned_proudstar.sql +3 -0
- package/templates/minimal-app/apps/server/drizzle/0003_silly_the_liberteens.sql +27 -0
- package/templates/minimal-app/apps/server/drizzle/meta/0000_snapshot.json.tpl +56 -166
- package/templates/minimal-app/apps/server/drizzle/meta/0001_snapshot.json.tpl +1796 -1910
- package/templates/minimal-app/apps/server/drizzle/meta/0002_snapshot.json.tpl +1818 -0
- package/templates/minimal-app/apps/server/drizzle/meta/0003_snapshot.json.tpl +2137 -0
- package/templates/minimal-app/apps/server/drizzle/meta/_journal.json.tpl +15 -1
- package/templates/minimal-app/apps/server/drizzle.config.ts.tpl +3 -33
- package/templates/minimal-app/apps/server/package.json.tpl +57 -56
- package/templates/minimal-app/apps/server/src/app.ts.tpl +149 -141
- package/templates/minimal-app/apps/server/src/index.ts.tpl +12 -65
- package/templates/minimal-app/apps/server/src/modules/conversation/conversation.mastra.ts.tpl +26 -0
- package/templates/minimal-app/apps/server/src/modules/demo-workflow/demo-workflow.module.ts.tpl +47 -0
- package/templates/minimal-app/apps/server/src/modules/demo-workflow/demo-workflow.service.ts.tpl +43 -0
- package/templates/minimal-app/apps/server/src/modules/demo-workflow/demo-workflow.trpc.ts.tpl +16 -0
- package/templates/minimal-app/apps/server/src/modules/posts/posts.db.ts.tpl +28 -28
- package/templates/minimal-app/apps/server/src/modules/posts/posts.grants.ts.tpl +28 -30
- package/templates/minimal-app/apps/server/src/modules/posts/posts.module.ts.tpl +54 -54
- package/templates/minimal-app/apps/server/src/modules/posts/posts.repository.ts.tpl +67 -67
- package/templates/minimal-app/apps/server/src/modules/posts/posts.service.ts.tpl +116 -115
- package/templates/minimal-app/apps/server/src/modules/posts/posts.trpc.ts.tpl +37 -37
- package/templates/minimal-app/apps/server/src/modules/test-harness/test-harness.module.ts.tpl +279 -279
- package/templates/minimal-app/apps/server/src/schema.ts.tpl +31 -20
- package/templates/minimal-app/apps/server/src/types.ts.tpl +12 -1
- package/templates/minimal-app/apps/server/tsconfig.json.tpl +1 -1
- package/templates/minimal-app/apps/server/tsup.config.ts.tpl +23 -9
- package/templates/minimal-app/apps/shared/.env.example.tpl +5 -0
- package/templates/minimal-app/apps/shared/.env.production.example.tpl +23 -0
- package/templates/minimal-app/apps/shared/.env.tpl +5 -0
- package/templates/minimal-app/apps/shared/Dockerfile.tpl +48 -0
- package/templates/minimal-app/apps/shared/fly.toml.tpl +24 -0
- package/templates/minimal-app/apps/shared/package.json.tpl +25 -24
- package/templates/minimal-app/apps/shared/scripts/fly-deploy.mjs.tpl +75 -0
- package/templates/minimal-app/apps/shared/scripts/fly-secrets.mjs.tpl +31 -0
- package/templates/minimal-app/apps/shared/src/modules/app/app.constants.ts.tpl +28 -28
- package/templates/minimal-app/apps/shared/src/modules/conversation/conversation.constants.ts.tpl +1 -0
- package/templates/minimal-app/apps/shared/src/modules/notification/notification.schema.ts.tpl +3 -3
- package/templates/minimal-app/apps/shared/src/modules/posts/posts.constants.ts.tpl +5 -5
- package/templates/minimal-app/apps/shared/src/modules/posts/posts.schema.ts.tpl +25 -25
- package/templates/minimal-app/apps/webapp/package.json.tpl +53 -53
- package/templates/minimal-app/apps/webapp/public/push-sw.js.tpl +34 -34
- package/templates/minimal-app/apps/webapp/src/App.tsx.tpl +46 -44
- package/templates/minimal-app/apps/webapp/src/Layout.tsx.tpl +96 -65
- package/templates/minimal-app/apps/webapp/src/Router.tsx.tpl +114 -93
- package/templates/minimal-app/apps/webapp/src/index.css.tpl +15 -15
- package/templates/minimal-app/apps/webapp/src/main.tsx.tpl +26 -26
- package/templates/minimal-app/apps/webapp/src/modules/conversation/ConversationRoute.tsx.tpl +36 -0
- package/templates/minimal-app/apps/webapp/src/modules/files/FilesRoute.tsx.tpl +88 -0
- package/templates/minimal-app/apps/webapp/src/modules/files/hooks/useFilesRoute.ts.tpl +50 -0
- package/templates/minimal-app/apps/webapp/src/modules/workflows/WorkflowsRoute.tsx.tpl +97 -0
- package/templates/minimal-app/apps/webapp/src/modules/workflows/hooks/useWorkflowsRoute.ts.tpl +64 -0
- package/templates/minimal-app/apps/webapp/src/utils/i18n.ts.tpl +13 -13
- package/templates/minimal-app/apps/webapp/src/utils/trpc.ts.tpl +10 -10
- package/templates/minimal-app/apps/webapp/src/vite-env.d.ts.tpl +1 -1
- package/templates/minimal-app/apps/webapp/translations/en/app.json.tpl +7 -7
- package/templates/minimal-app/apps/webapp/translations/en/{{APP_SLUG}}.json.tpl +193 -135
- package/templates/minimal-app/apps/webapp/tsconfig.json.tpl +17 -17
- package/templates/minimal-app/apps/webapp/vite.config.ts.tpl +31 -31
- package/templates/minimal-app/biome.json.tpl +17 -12
- package/templates/minimal-app/package.json.tpl +9 -5
- package/templates/minimal-app/pnpm-workspace.yaml.tpl +67 -58
- package/templates/minimal-app/template.manifest.json +92 -2
- package/templates/minimal-app/apps/server/drizzle/db.ts.tpl +0 -26
- package/templates/minimal-app/apps/server/drizzle/guard.ts.tpl +0 -36
- package/templates/minimal-app/apps/server/drizzle/reset.ts.tpl +0 -40
- package/templates/minimal-app/apps/server/drizzle/sync.ts.tpl +0 -16
- package/templates/minimal-app/apps/server/src/lib/auth.ts.tpl +0 -12
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
## Workspace
|
|
6
6
|
|
|
7
|
-
- `apps/shared` contains shared contracts
|
|
7
|
+
- `apps/shared` contains shared contracts, constants, and the product Deploy home (Dockerfile, `fly.toml`).
|
|
8
8
|
- `apps/server` contains the Express, Better Auth, Drizzle, and tRPC backend.
|
|
9
9
|
- `apps/webapp` contains the Vite, React Router, HeroUI, and `nuqs` frontend.
|
|
10
|
+
- `apps/landing` contains the public marketing site (one page) and its Fly adapter.
|
|
10
11
|
- `apps/email` contains the email templates and local delivery registry used by the starter.
|
|
11
12
|
|
|
12
13
|
## Getting Started
|
|
@@ -26,26 +27,56 @@ Database tables are registered by hand in `apps/server/src/schema.ts`; after cha
|
|
|
26
27
|
- Email: `admin@{{APP_SLUG}}.local`
|
|
27
28
|
- Password: `password1234`
|
|
28
29
|
|
|
29
|
-
## Typical Commands
|
|
30
|
+
## Typical Commands
|
|
30
31
|
|
|
31
32
|
```sh
|
|
32
33
|
pnpm dev
|
|
33
34
|
pnpm build
|
|
34
35
|
pnpm check-types
|
|
35
|
-
pnpm lint
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Managed framework updates
|
|
39
|
-
|
|
40
|
-
This app records its generated baseline in `.m5kdev.json`. The updater is run
|
|
41
|
-
explicitly from the package registry and is not installed as an app dependency:
|
|
42
|
-
|
|
43
|
-
```sh
|
|
44
|
-
pnpm dlx create-m5kdev@<version> doctor
|
|
45
|
-
pnpm dlx create-m5kdev@<version> update --dry-run
|
|
46
|
-
pnpm dlx create-m5kdev@<version> update
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Use an exact target version in CI and when coordinating an upgrade. Existing
|
|
50
|
-
projects without `.m5kdev.json` can enroll at their current compatible baseline
|
|
51
|
-
with `pnpm dlx create-m5kdev@<version> init`.
|
|
36
|
+
pnpm lint
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Managed framework updates
|
|
40
|
+
|
|
41
|
+
This app records its generated baseline in `.m5kdev.json`. The updater is run
|
|
42
|
+
explicitly from the package registry and is not installed as an app dependency:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
pnpm dlx create-m5kdev@<version> doctor
|
|
46
|
+
pnpm dlx create-m5kdev@<version> update --dry-run
|
|
47
|
+
pnpm dlx create-m5kdev@<version> update
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Use an exact target version in CI and when coordinating an upgrade. Existing
|
|
51
|
+
projects without `.m5kdev.json` can enroll at their current compatible baseline
|
|
52
|
+
with `pnpm dlx create-m5kdev@<version> init`.
|
|
53
|
+
|
|
54
|
+
## Deploy (Fly.io)
|
|
55
|
+
|
|
56
|
+
The Dockerfile is the portable image. Fly is the adapter this starter ships —
|
|
57
|
+
`fly.toml` is ignored by `create-m5kdev update` so your app name and region stay
|
|
58
|
+
yours.
|
|
59
|
+
|
|
60
|
+
`.env*` files are excluded from the image. Copy the examples, then pass values
|
|
61
|
+
as Fly **build secrets** (baked into the SPA at image build) and **runtime
|
|
62
|
+
secrets** (`REDIS_URL`, `DATABASE_URL`, auth).
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
cp apps/shared/.env.production.example apps/shared/.env.production
|
|
66
|
+
cp apps/landing/.env.production.example apps/landing/.env.production
|
|
67
|
+
# fill in URLs, BETTER_AUTH_SECRET, REDIS_URL, …
|
|
68
|
+
|
|
69
|
+
fly apps create {{APP_SLUG}}-app
|
|
70
|
+
fly apps create {{APP_SLUG}}-landing
|
|
71
|
+
fly volumes create libsql_data --app {{APP_SLUG}}-app --region iad --size 1
|
|
72
|
+
pnpm app:secrets
|
|
73
|
+
pnpm landing:secrets
|
|
74
|
+
pnpm app:deploy
|
|
75
|
+
pnpm landing:deploy
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`app:deploy` / `landing:deploy` read that app’s `.env.production` and forward
|
|
79
|
+
every key as `fly deploy --build-secret`. A missing env file errors with a
|
|
80
|
+
copy-the-example message. Product data lives on the `libsql_data` volume at
|
|
81
|
+
`/app/data` (`DATABASE_URL=file:/app/data/local.db`). Redis is a runtime secret,
|
|
82
|
+
not an image layer.
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "{{PACKAGE_SCOPE}}/e2e",
|
|
3
|
-
"version": "0.0.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "tsc --noEmit",
|
|
7
|
-
"lint": "biome check .",
|
|
8
|
-
"lint:fix": "biome check . --write",
|
|
9
|
-
"check-types": "tsc --noEmit",
|
|
10
|
-
"test:e2e": "playwright test",
|
|
11
|
-
"test:e2e:expo": "playwright test --config playwright.expo.config.ts --headed"
|
|
12
|
-
},
|
|
13
|
-
"devDependencies": {
|
|
14
|
-
"@m5kdev/backend": "catalog:",
|
|
15
|
-
"@m5kdev/commons": "catalog:",
|
|
16
|
-
"@m5kdev/config": "catalog:",
|
|
17
|
-
"@playwright/test": "catalog:",
|
|
18
|
-
"{{PACKAGE_SCOPE}}/shared": "workspace:*",
|
|
19
|
-
"@trpc/client": "catalog:",
|
|
20
|
-
"@types/node": "catalog:",
|
|
21
|
-
"typescript": "catalog:"
|
|
22
|
-
}
|
|
23
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PACKAGE_SCOPE}}/e2e",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "tsc --noEmit",
|
|
7
|
+
"lint": "biome check .",
|
|
8
|
+
"lint:fix": "biome check . --write",
|
|
9
|
+
"check-types": "tsc --noEmit",
|
|
10
|
+
"test:e2e": "playwright test",
|
|
11
|
+
"test:e2e:expo": "playwright test --config playwright.expo.config.ts --headed"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@m5kdev/backend": "catalog:m5kdev",
|
|
15
|
+
"@m5kdev/commons": "catalog:m5kdev",
|
|
16
|
+
"@m5kdev/config": "catalog:m5kdev",
|
|
17
|
+
"@playwright/test": "catalog:m5kdev",
|
|
18
|
+
"{{PACKAGE_SCOPE}}/shared": "workspace:*",
|
|
19
|
+
"@trpc/client": "catalog:m5kdev",
|
|
20
|
+
"@types/node": "catalog:m5kdev",
|
|
21
|
+
"typescript": "catalog:m5kdev"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,39 +1,51 @@
|
|
|
1
|
-
import { defineConfig, devices } from "@playwright/test";
|
|
2
|
-
import { BASE_URLS, serverWebServer, webappWebServer } from "./servers";
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
testDir: "./tests",
|
|
6
|
-
fullyParallel: false,
|
|
7
|
-
workers: 1,
|
|
8
|
-
forbidOnly: Boolean(process.env.CI),
|
|
9
|
-
retries: process.env.CI ? 2 : 0,
|
|
10
|
-
reporter: [["list"], ["html", { open: "never" }]],
|
|
11
|
-
use: {
|
|
12
|
-
trace: "on-first-retry",
|
|
13
|
-
},
|
|
14
|
-
webServer: [
|
|
15
|
-
serverWebServer("standard"),
|
|
16
|
-
webappWebServer("standard"),
|
|
17
|
-
serverWebServer("waitlist"),
|
|
18
|
-
webappWebServer("waitlist"),
|
|
19
|
-
],
|
|
20
|
-
projects: [
|
|
21
|
-
{
|
|
22
|
-
name: "standard",
|
|
23
|
-
// exact filenames — a broad regex would also match the expo-*.spec files
|
|
24
|
-
testMatch: [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
import { defineConfig, devices } from "@playwright/test";
|
|
2
|
+
import { BASE_URLS, serverWebServer, webappWebServer } from "./servers";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
testDir: "./tests",
|
|
6
|
+
fullyParallel: false,
|
|
7
|
+
workers: 1,
|
|
8
|
+
forbidOnly: Boolean(process.env.CI),
|
|
9
|
+
retries: process.env.CI ? 2 : 0,
|
|
10
|
+
reporter: [["list"], ["html", { open: "never" }]],
|
|
11
|
+
use: {
|
|
12
|
+
trace: "on-first-retry",
|
|
13
|
+
},
|
|
14
|
+
webServer: [
|
|
15
|
+
serverWebServer("standard"),
|
|
16
|
+
webappWebServer("standard"),
|
|
17
|
+
serverWebServer("waitlist"),
|
|
18
|
+
webappWebServer("waitlist"),
|
|
19
|
+
],
|
|
20
|
+
projects: [
|
|
21
|
+
{
|
|
22
|
+
name: "standard",
|
|
23
|
+
// exact filenames — a broad regex would also match the expo-*.spec files
|
|
24
|
+
testMatch: [
|
|
25
|
+
"standard.spec.ts",
|
|
26
|
+
"email.spec.ts",
|
|
27
|
+
// m5k:ai:start
|
|
28
|
+
"conversation.spec.ts",
|
|
29
|
+
// m5k:ai:end
|
|
30
|
+
// m5k:files:start
|
|
31
|
+
"files.spec.ts",
|
|
32
|
+
// m5k:files:end
|
|
33
|
+
// m5k:workflows:start
|
|
34
|
+
"workflow.spec.ts",
|
|
35
|
+
// m5k:workflows:end
|
|
36
|
+
],
|
|
37
|
+
use: {
|
|
38
|
+
...devices["Desktop Chrome"],
|
|
39
|
+
baseURL: BASE_URLS.standard,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "waitlist",
|
|
44
|
+
testMatch: ["waitlist.spec.ts", "email.spec.ts"],
|
|
45
|
+
use: {
|
|
46
|
+
...devices["Desktop Chrome"],
|
|
47
|
+
baseURL: BASE_URLS.waitlist,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
});
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
import { defineConfig, devices } from "@playwright/test";
|
|
2
|
-
import { EXPO_BASE_URLS, expoWebServer, serverWebServer } from "./servers";
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
testDir: "./tests",
|
|
6
|
-
fullyParallel: false,
|
|
7
|
-
workers: 1,
|
|
8
|
-
forbidOnly: Boolean(process.env.CI),
|
|
9
|
-
retries: process.env.CI ? 2 : 0,
|
|
10
|
-
reporter: [["list"], ["html", { open: "never" }]],
|
|
11
|
-
use: {
|
|
12
|
-
trace: "on-first-retry",
|
|
13
|
-
},
|
|
14
|
-
webServer: [
|
|
15
|
-
serverWebServer("standard", { expo: true }),
|
|
16
|
-
expoWebServer("standard"),
|
|
17
|
-
serverWebServer("waitlist", { expo: true }),
|
|
18
|
-
expoWebServer("waitlist"),
|
|
19
|
-
],
|
|
20
|
-
projects: [
|
|
21
|
-
{
|
|
22
|
-
name: "expo-standard",
|
|
23
|
-
testMatch: /.*expo-standard\.spec\.ts/,
|
|
24
|
-
use: {
|
|
25
|
-
...devices["Desktop Chrome"],
|
|
26
|
-
baseURL: EXPO_BASE_URLS.standard,
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
name: "expo-waitlist",
|
|
31
|
-
testMatch: /.*expo-waitlist\.spec\.ts/,
|
|
32
|
-
use: {
|
|
33
|
-
...devices["Desktop Chrome"],
|
|
34
|
-
baseURL: EXPO_BASE_URLS.waitlist,
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
],
|
|
38
|
-
});
|
|
1
|
+
import { defineConfig, devices } from "@playwright/test";
|
|
2
|
+
import { EXPO_BASE_URLS, expoWebServer, serverWebServer } from "./servers";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
testDir: "./tests",
|
|
6
|
+
fullyParallel: false,
|
|
7
|
+
workers: 1,
|
|
8
|
+
forbidOnly: Boolean(process.env.CI),
|
|
9
|
+
retries: process.env.CI ? 2 : 0,
|
|
10
|
+
reporter: [["list"], ["html", { open: "never" }]],
|
|
11
|
+
use: {
|
|
12
|
+
trace: "on-first-retry",
|
|
13
|
+
},
|
|
14
|
+
webServer: [
|
|
15
|
+
serverWebServer("standard", { expo: true }),
|
|
16
|
+
expoWebServer("standard"),
|
|
17
|
+
serverWebServer("waitlist", { expo: true }),
|
|
18
|
+
expoWebServer("waitlist"),
|
|
19
|
+
],
|
|
20
|
+
projects: [
|
|
21
|
+
{
|
|
22
|
+
name: "expo-standard",
|
|
23
|
+
testMatch: /.*expo-standard\.spec\.ts/,
|
|
24
|
+
use: {
|
|
25
|
+
...devices["Desktop Chrome"],
|
|
26
|
+
baseURL: EXPO_BASE_URLS.standard,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "expo-waitlist",
|
|
31
|
+
testMatch: /.*expo-waitlist\.spec\.ts/,
|
|
32
|
+
use: {
|
|
33
|
+
...devices["Desktop Chrome"],
|
|
34
|
+
baseURL: EXPO_BASE_URLS.waitlist,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
});
|
|
@@ -1,112 +1,136 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared webServer definitions for the Playwright configs. Each profile runs
|
|
3
|
-
* an isolated stack: own port pair, own SQLite file, own email output dir, and
|
|
4
|
-
* own Redis DB index (queue names are identical across profiles — sharing a
|
|
5
|
-
* Redis DB would let one profile's workers consume the other's jobs).
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export type E2EProfile = "standard" | "waitlist";
|
|
9
|
-
|
|
10
|
-
const SERVER_FILTER = "pnpm --filter {{PACKAGE_SCOPE}}/server exec";
|
|
11
|
-
const WEBAPP_FILTER = "pnpm --filter {{PACKAGE_SCOPE}}/webapp exec";
|
|
12
|
-
|
|
13
|
-
const SIGNOZ_OTLP_ENDPOINT =
|
|
14
|
-
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ??
|
|
15
|
-
"https://signoz-ingester-production-9090.up.railway.app";
|
|
16
|
-
|
|
17
|
-
const PORTS: Record<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Shared webServer definitions for the Playwright configs. Each profile runs
|
|
3
|
+
* an isolated stack: own port pair, own SQLite file, own email output dir, and
|
|
4
|
+
* own Redis DB index (queue names are identical across profiles — sharing a
|
|
5
|
+
* Redis DB would let one profile's workers consume the other's jobs).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type E2EProfile = "standard" | "waitlist";
|
|
9
|
+
|
|
10
|
+
const SERVER_FILTER = "pnpm --filter {{PACKAGE_SCOPE}}/server exec";
|
|
11
|
+
const WEBAPP_FILTER = "pnpm --filter {{PACKAGE_SCOPE}}/webapp exec";
|
|
12
|
+
|
|
13
|
+
const SIGNOZ_OTLP_ENDPOINT =
|
|
14
|
+
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ??
|
|
15
|
+
"https://signoz-ingester-production-9090.up.railway.app";
|
|
16
|
+
|
|
17
|
+
const PORTS: Record<
|
|
18
|
+
E2EProfile,
|
|
19
|
+
{
|
|
20
|
+
web: number;
|
|
21
|
+
server: number;
|
|
22
|
+
expoWeb: number;
|
|
23
|
+
expoServer: number;
|
|
24
|
+
redisDb: number;
|
|
25
|
+
expoRedisDb: number;
|
|
26
|
+
}
|
|
27
|
+
> = {
|
|
28
|
+
standard: {
|
|
29
|
+
web: 15173,
|
|
30
|
+
server: 18180,
|
|
31
|
+
expoWeb: 15183,
|
|
32
|
+
expoServer: 18182,
|
|
33
|
+
redisDb: 1,
|
|
34
|
+
expoRedisDb: 3,
|
|
35
|
+
},
|
|
36
|
+
waitlist: {
|
|
37
|
+
web: 15174,
|
|
38
|
+
server: 18181,
|
|
39
|
+
expoWeb: 15184,
|
|
40
|
+
expoServer: 18183,
|
|
41
|
+
redisDb: 2,
|
|
42
|
+
expoRedisDb: 4,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
function serverEnv(profile: E2EProfile, expo: boolean): Record<string, string> {
|
|
47
|
+
const ports = PORTS[profile];
|
|
48
|
+
const serverPort = expo ? ports.expoServer : ports.server;
|
|
49
|
+
const webPort = expo ? ports.expoWeb : ports.web;
|
|
50
|
+
const suffix = expo ? `${profile}-expo` : profile;
|
|
51
|
+
return {
|
|
52
|
+
PORT: String(serverPort),
|
|
53
|
+
VITE_SERVER_URL: `http://127.0.0.1:${serverPort}`,
|
|
54
|
+
VITE_APP_URL: `http://127.0.0.1:${webPort}`,
|
|
55
|
+
DATABASE_URL: `file:./.e2e/${suffix}.db`,
|
|
56
|
+
EMAIL_OUTPUT_DIRECTORY: `.e2e/emails-${suffix}`,
|
|
57
|
+
PROVISIONED_EMAIL_DOMAIN: "provisioned.auth-e2e.local",
|
|
58
|
+
REDIS_URL: `redis://127.0.0.1:6379/${expo ? PORTS[profile].expoRedisDb : PORTS[profile].redisDb}`,
|
|
59
|
+
VITE_ENABLE_WAITLIST: profile === "waitlist" ? "true" : "false",
|
|
60
|
+
AUTH_E2E_PROFILE: profile,
|
|
61
|
+
BETTER_AUTH_SECRET: "auth-e2e-local-secret-auth-e2e-local-secret",
|
|
62
|
+
SYSTEM_NOTIFICATION_EMAIL: "ops@auth-e2e.local",
|
|
63
|
+
NODE_ENV: "development",
|
|
64
|
+
// hermetic: a real key in the invoking shell would flip email mode to
|
|
65
|
+
// "send" and the stored-email assertions would find nothing
|
|
66
|
+
RESEND_API_KEY: "",
|
|
67
|
+
...(process.env.OTEL_SDK_DISABLED === "true"
|
|
68
|
+
? {}
|
|
69
|
+
: {
|
|
70
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: SIGNOZ_OTLP_ENDPOINT,
|
|
71
|
+
OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf",
|
|
72
|
+
OTEL_SERVICE_NAME: `starter-server-e2e-${suffix}`,
|
|
73
|
+
OTEL_RESOURCE_ATTRIBUTES: `deployment.environment=e2e,e2e.profile=${profile},e2e.platform=${expo ? "expo" : "web"}`,
|
|
74
|
+
}),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function serverWebServer(profile: E2EProfile, { expo = false } = {}) {
|
|
79
|
+
const env = serverEnv(profile, expo);
|
|
80
|
+
return {
|
|
81
|
+
command: [
|
|
82
|
+
`${SERVER_FILTER} tsx db.ts reset`,
|
|
83
|
+
`${SERVER_FILTER} drizzle-kit migrate`,
|
|
84
|
+
`${SERVER_FILTER} tsx db.e2e.ts seed`,
|
|
85
|
+
`${SERVER_FILTER} tsx src/index.ts`,
|
|
86
|
+
].join(" && "),
|
|
87
|
+
url: `${env.VITE_SERVER_URL}/__emails`,
|
|
88
|
+
reuseExistingServer: !process.env.CI,
|
|
89
|
+
timeout: 120_000,
|
|
90
|
+
env,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function webappWebServer(profile: E2EProfile) {
|
|
95
|
+
const ports = PORTS[profile];
|
|
96
|
+
const env = serverEnv(profile, false);
|
|
97
|
+
return {
|
|
98
|
+
command: `${WEBAPP_FILTER} vite --host 127.0.0.1 --port ${ports.web}`,
|
|
99
|
+
url: `http://127.0.0.1:${ports.web}`,
|
|
100
|
+
reuseExistingServer: !process.env.CI,
|
|
101
|
+
timeout: 120_000,
|
|
102
|
+
env: {
|
|
103
|
+
VITE_SERVER_URL: env.VITE_SERVER_URL,
|
|
104
|
+
VITE_APP_URL: env.VITE_APP_URL,
|
|
105
|
+
VITE_ENABLE_WAITLIST: env.VITE_ENABLE_WAITLIST,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function expoWebServer(profile: E2EProfile) {
|
|
111
|
+
const ports = PORTS[profile];
|
|
112
|
+
const env = serverEnv(profile, true);
|
|
113
|
+
return {
|
|
114
|
+
command: `pnpm --filter {{PACKAGE_SCOPE}}/expo exec expo start --web --port ${ports.expoWeb} --host localhost`,
|
|
115
|
+
url: `http://127.0.0.1:${ports.expoWeb}`,
|
|
116
|
+
reuseExistingServer: !process.env.CI,
|
|
117
|
+
timeout: 180_000,
|
|
118
|
+
env: {
|
|
119
|
+
EXPO_PUBLIC_SERVER_URL: env.VITE_SERVER_URL,
|
|
120
|
+
EXPO_PUBLIC_APP_URL: `http://127.0.0.1:${ports.expoWeb}`,
|
|
121
|
+
EXPO_PUBLIC_ENABLE_WAITLIST: env.VITE_ENABLE_WAITLIST,
|
|
122
|
+
EXPO_NO_TELEMETRY: "1",
|
|
123
|
+
BROWSER: "none",
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const BASE_URLS: Record<E2EProfile, string> = {
|
|
129
|
+
standard: `http://127.0.0.1:${PORTS.standard.web}`,
|
|
130
|
+
waitlist: `http://127.0.0.1:${PORTS.waitlist.web}`,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export const EXPO_BASE_URLS: Record<E2EProfile, string> = {
|
|
134
|
+
standard: `http://127.0.0.1:${PORTS.standard.expoWeb}`,
|
|
135
|
+
waitlist: `http://127.0.0.1:${PORTS.waitlist.expoWeb}`,
|
|
136
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
import { clearEmails, login, signUp, verifyLatestEmail } from "./helpers";
|
|
3
|
+
|
|
4
|
+
const profile = "standard" as const;
|
|
5
|
+
|
|
6
|
+
test.beforeEach(async ({ request }) => {
|
|
7
|
+
await clearEmails(request, profile);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("open the agent conversation and see an empty transcript", async ({ page, request }) => {
|
|
11
|
+
const email = `conversation.${Date.now()}@auth-e2e.local`;
|
|
12
|
+
const password = "password1234";
|
|
13
|
+
|
|
14
|
+
await signUp(page, email, password);
|
|
15
|
+
await verifyLatestEmail(request, profile, email);
|
|
16
|
+
await login(page, email, password);
|
|
17
|
+
|
|
18
|
+
await page.goto("/conversation");
|
|
19
|
+
await expect(page.getByTestId("conversation-route")).toBeVisible();
|
|
20
|
+
await expect(page.getByText("No messages yet")).toBeVisible();
|
|
21
|
+
await expect(page.getByRole("button", { name: "Send" })).toBeVisible();
|
|
22
|
+
});
|