genesis-stack 1.3.0 → 1.4.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/README.md +19 -3
- package/genesis.templates.json +48 -0
- package/package.json +1 -1
- package/stacks/pieces/django-mysql.md +79 -0
- package/stacks/pieces/django-postgresql.md +78 -0
- package/stacks/pieces/django-sqlite.md +55 -0
- package/stacks/pieces/django.md +166 -0
- package/stacks/pieces/express.md +161 -0
- package/stacks/pieces/java.md +1 -2
- package/stacks/pieces/jskit.md +31 -1
- package/stacks/pieces/nextjs.md +181 -0
- package/stacks/pieces/nodejs.md +13 -1
- package/stacks/pieces/python.md +18 -5
- package/stacks/pieces/rails-mysql.md +81 -0
- package/stacks/pieces/rails-postgresql.md +86 -0
- package/stacks/pieces/rails-sqlite.md +60 -0
- package/stacks/pieces/rails.md +188 -0
- package/stacks/pieces/ruby.md +1 -4
- package/stacks/pieces/spring-boot-mysql.md +74 -0
- package/stacks/pieces/spring-boot-postgresql.md +68 -0
- package/stacks/pieces/spring-boot.md +154 -0
- package/stacks/pieces/sqlite.md +6 -0
package/stacks/pieces/jskit.md
CHANGED
|
@@ -32,6 +32,15 @@ https://mobily-enterprises.github.io/jskit-ai/
|
|
|
32
32
|
`AUTH_LOCAL_SESSION_SECRET` as a required environment name in the project's
|
|
33
33
|
established environment contract and committed environment example. Never
|
|
34
34
|
commit or invent its value.
|
|
35
|
+
- An application with accounts always has the host's browser-preview login,
|
|
36
|
+
without waiting to be asked: when adding authentication, add the
|
|
37
|
+
`auth/auth-surface` pattern's executable `tools/preview-identity` and copy its
|
|
38
|
+
exact `#### Preview identity` block (Command `tools/preview-identity`,
|
|
39
|
+
Protocol `vibe64.preview-identity.command.v1`, Identity types `email`
|
|
40
|
+
`user-id`, Enabled environment `AUTH_DEV_BYPASS_ENABLED`, Secret environment
|
|
41
|
+
`AUTH_DEV_BYPASS_SECRET`, Runtimes `nodejs`) under the web `Outputs` target.
|
|
42
|
+
Which existing accounts the preview uses stays the person's choice; never
|
|
43
|
+
create users for it.
|
|
35
44
|
- Before creating or modifying JSKIT Vue/Vuetify UI, read the Material 3
|
|
36
45
|
contract at
|
|
37
46
|
`https://mobily-enterprises.github.io/jskit-ai/guide/framework/material-3`
|
|
@@ -77,6 +86,25 @@ https://mobily-enterprises.github.io/jskit-ai/
|
|
|
77
86
|
input fields never grant administrator access. Verify the requested provider
|
|
78
87
|
outcomes and denied access with controlled fixtures. Genesis transports
|
|
79
88
|
guidance and opaque declarations; it does not execute integrations or payments.
|
|
89
|
+
- Shipping the app to phones ("install on my phone"): the host-owned
|
|
90
|
+
`## Packaging` section is written only when the person adds a mobile target.
|
|
91
|
+
It declares a separate `web-bundle` package whose Build produces the bundled
|
|
92
|
+
client (Output its build folder) with the absolute HTTPS API base the client
|
|
93
|
+
calls, then a `capacitor` package with `Content: package <that id>`,
|
|
94
|
+
`Platforms: android`, a permanent reverse-DNS `Id`, `Name`, a committed
|
|
95
|
+
1024x1024 PNG `Icon` without transparency, `Version from: package.json` and
|
|
96
|
+
one `Permission` line, with a plain reason, per native capability. The host
|
|
97
|
+
generates and discards the native project on every build: never commit
|
|
98
|
+
`android/`, `ios/`, `capacitor.config.*`, Gradle files, build numbers or
|
|
99
|
+
signing keys. Native plugins are ordinary client dependencies at the exact
|
|
100
|
+
versions in `package-lock.json`, and the host's shell is Capacitor 8; it
|
|
101
|
+
blocks a lockfile mismatch or another major. `@jskit-ai/mobile-capacitor` is
|
|
102
|
+
still on Capacitor 7, so propose mobile packaging for a JSKIT client only
|
|
103
|
+
once its Capacitor dependencies are 8.x. A deep-link scheme and app-link
|
|
104
|
+
domains live once in `## Environment defaults` (for example `APP_URL_SCHEME`,
|
|
105
|
+
`APP_LINK_DOMAINS`) and Packaging names them with `Deep link scheme from` and
|
|
106
|
+
`App link domains from`; the server's CORS and OAuth callbacks must accept
|
|
107
|
+
the app's origin and scheme.
|
|
80
108
|
|
|
81
109
|
## Adoption
|
|
82
110
|
|
|
@@ -96,7 +124,9 @@ https://mobily-enterprises.github.io/jskit-ai/
|
|
|
96
124
|
component when the script or preparation file does not exist.
|
|
97
125
|
- When the project declares an application-owned identity exchange for a host's
|
|
98
126
|
browser preview, preserve its command, selectors, protocol, environment names,
|
|
99
|
-
runtime and timeout in the project's existing section.
|
|
127
|
+
runtime and timeout in the project's existing section. When an application
|
|
128
|
+
with JSKIT accounts lacks it, add it from the `auth/auth-surface` pattern as
|
|
129
|
+
in Guidance.
|
|
100
130
|
A host-saved identity name/value is not a substitute for this application
|
|
101
131
|
contract.
|
|
102
132
|
- Treat generator descriptors, receipts, sync commands, legacy service
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Stack piece: nextjs
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Next.js React application conventions: App Router or Pages Router, the
|
|
6
|
+
`next` CLI, Server Actions, middleware, environment variables, builds and
|
|
7
|
+
production serving. A Next.js application has `next` in `package.json`
|
|
8
|
+
dependencies and usually a `next.config.js`, `next.config.mjs` or
|
|
9
|
+
`next.config.ts` file and an `app/` or `pages/` directory. Authoritative
|
|
10
|
+
framework documentation: https://nextjs.org/docs
|
|
11
|
+
|
|
12
|
+
## Requires
|
|
13
|
+
|
|
14
|
+
- `nodejs`
|
|
15
|
+
|
|
16
|
+
## Conflicts
|
|
17
|
+
|
|
18
|
+
- `express`
|
|
19
|
+
|
|
20
|
+
## Guidance
|
|
21
|
+
|
|
22
|
+
- Match the installed Next.js major version and the router the application
|
|
23
|
+
already uses (`app/` App Router or `pages/` Pages Router). Recent releases
|
|
24
|
+
ship version-matched documentation in `node_modules/next/dist/docs/`; read
|
|
25
|
+
the relevant guide there before relying on remembered APIs. `next dev` may
|
|
26
|
+
write a framework-owned agent-rules block into `AGENTS.md`; commit it rather
|
|
27
|
+
than repeatedly removing it.
|
|
28
|
+
- Bind the development server to the host and port it is given:
|
|
29
|
+
`next dev --hostname <host> --port <port>` (the proposed Run passes them
|
|
30
|
+
through `npm run dev --`). Without `--hostname`, `next dev` and `next start`
|
|
31
|
+
listen on every interface. Never hard-code a port in `package.json` scripts.
|
|
32
|
+
- Behind a development reverse proxy on loopback that rewrites `Host` and sends
|
|
33
|
+
`X-Forwarded-Host`, `X-Forwarded-Proto` and `X-Forwarded-Port`, Next.js
|
|
34
|
+
builds request URLs from the forwarded headers. The development server blocks
|
|
35
|
+
requests for its own development resources (the `/_next/hmr` WebSocket and
|
|
36
|
+
other `/_next/*` dev endpoints) whose `Origin` hostname is not `localhost`,
|
|
37
|
+
the hostname it was started with, or an `allowedDevOrigins` entry. A proxy
|
|
38
|
+
that rewrites the browser's `Origin` to the loopback address needs no entry;
|
|
39
|
+
otherwise add the browser-facing hostname pattern to `allowedDevOrigins`,
|
|
40
|
+
read from an environment variable rather than hard-coded. The HMR client
|
|
41
|
+
connects through the page's own origin; do not hard-code an asset prefix or
|
|
42
|
+
WebSocket host for the proxy.
|
|
43
|
+
- Server Actions reject a POST whose `Origin` host differs from
|
|
44
|
+
`X-Forwarded-Host` (or `Host` without it) with "Invalid Server Actions
|
|
45
|
+
request". A proxy that forwards both unchanged, or presents a same-origin
|
|
46
|
+
request entirely on the loopback origin (loopback `Origin` and `Host`, no
|
|
47
|
+
forwarded host), needs no setting. Add an exact host to
|
|
48
|
+
`experimental.serverActions.allowedOrigins` only for a real reported
|
|
49
|
+
mismatch, in development only (ports cannot be wildcarded); the list also
|
|
50
|
+
applies in production, so never admit arbitrary origins.
|
|
51
|
+
- Redirect with relative paths. A Server Action's redirect travels in a
|
|
52
|
+
framework response header, not `Location`, so a proxy does not rewrite it,
|
|
53
|
+
and Auth.js `signIn`/`signOut` with `redirectTo` build an absolute URL from
|
|
54
|
+
the request's host headers, which a proxy may present as the loopback
|
|
55
|
+
address. Call them with `redirect: false`, then `redirect("/path")`.
|
|
56
|
+
`request.nextUrl` in `proxy`/middleware names the server's own host, so an
|
|
57
|
+
Auth.js `callbackUrl` may be a loopback URL: use only its path.
|
|
58
|
+
- `NEXT_PUBLIC_*` variables are inlined into client bundles at build time:
|
|
59
|
+
never put secrets in them, and their production values must exist when
|
|
60
|
+
`next build` runs, not only at start. Server-only values are read from
|
|
61
|
+
`process.env` at request time. Next.js reads `.env*` files but the
|
|
62
|
+
environment wins; keep real values out of committed `.env*` files.
|
|
63
|
+
- With Auth.js (`next-auth` v5), supply `AUTH_SECRET` through the environment
|
|
64
|
+
(generate with `openssl rand -base64 33`; `npx auth secret` writes it into a
|
|
65
|
+
file instead) and set `AUTH_TRUST_HOST=true` when the app is served behind a
|
|
66
|
+
trusted reverse proxy, so callback and redirect URLs use the forwarded
|
|
67
|
+
origin. Other auth libraries need their equivalent trusted-host setting.
|
|
68
|
+
- With `cacheComponents` enabled (the recent `create-next-app` default),
|
|
69
|
+
pages that read the session must render at request time: call
|
|
70
|
+
`await connection()` before `auth()`, wrap the read in `<Suspense>`, or
|
|
71
|
+
export `instant = false`; otherwise `next build` fails. Gate protected
|
|
72
|
+
routes in `proxy`/middleware (Auth.js `authorized` callback), not only with
|
|
73
|
+
`redirect()` during render: the client router can replay a cached
|
|
74
|
+
render-time redirect to the login page after sign-in.
|
|
75
|
+
- Readiness and health probes must reach a public route: middleware (or
|
|
76
|
+
`proxy`) that redirects `/` to a login page makes a `GET /` probe fail.
|
|
77
|
+
Exclude the probe path from the auth matcher, or add a small public route
|
|
78
|
+
handler (for example `app/health/route.ts`) and point the Outputs and
|
|
79
|
+
Deployment readiness checks at it.
|
|
80
|
+
- Database access goes through the application's ORM (Prisma, Drizzle, Kysely
|
|
81
|
+
or another). Its schema migrations are application-owned: deployment runs the
|
|
82
|
+
non-interactive apply command (for example `prisma migrate deploy`), never
|
|
83
|
+
`prisma migrate dev` or `prisma db push` against supplied data. Seed scripts
|
|
84
|
+
must be idempotent. Tests use a disposable database supplied for them, never
|
|
85
|
+
the development or production database. Declare the database Resources in
|
|
86
|
+
the project Stack; this piece does not choose a database.
|
|
87
|
+
- Production: `next build` then `next start`. `next start` reads `PORT` but not
|
|
88
|
+
`HOST`; bind it explicitly (`next start --hostname <host>`), as the proposed
|
|
89
|
+
Serve does. Set `NODE_ENV=production` only through the production
|
|
90
|
+
environment, never as a project-wide default; `next build` and `next start`
|
|
91
|
+
set it themselves. `output: "standalone"` changes the start command to
|
|
92
|
+
`node .next/standalone/server.js` (which reads `HOSTNAME` and `PORT`) and
|
|
93
|
+
requires copying `public/` and `.next/static/`; update Deployment if the
|
|
94
|
+
application uses it. `output: "export"` produces static files with no server.
|
|
95
|
+
- Do not run `next build` into the same `.next` directory a running `next dev`
|
|
96
|
+
uses unless the installed major isolates development output (Next.js 16 and
|
|
97
|
+
later write development output to `.next/dev`); with older majors stop the
|
|
98
|
+
development server first or build into a separate `distDir`.
|
|
99
|
+
- When the application has login, seed one administrator and one ordinary user
|
|
100
|
+
for development through an idempotent seed script with credentials from the
|
|
101
|
+
environment, and keep role checks on the server (Server Components, route
|
|
102
|
+
handlers, Server Actions), not only in client components.
|
|
103
|
+
- Shipping the app to phones ("install on my phone") needs a static client:
|
|
104
|
+
`output: "export"` (no Server Actions, route handlers, middleware or
|
|
105
|
+
request-time rendering in that build), with API calls going to an absolute
|
|
106
|
+
HTTPS base read from a `NEXT_PUBLIC_*` variable. The host-owned
|
|
107
|
+
`## Packaging` section, written only when the person adds a mobile target,
|
|
108
|
+
declares a `web-bundle` package (Build `npm` `run` `build`, Output `out`)
|
|
109
|
+
and a `capacitor` package with `Content: package <that id>`,
|
|
110
|
+
`Platforms: android`, a permanent reverse-DNS `Id`, `Name`, a committed
|
|
111
|
+
1024x1024 PNG `Icon` without transparency, `Version from: package.json` and
|
|
112
|
+
one `Permission` line per native capability. Native plugins are ordinary
|
|
113
|
+
dependencies at exact `package-lock.json` versions on Capacitor 8; the host
|
|
114
|
+
generates and discards the native project, so never commit `android/`,
|
|
115
|
+
`capacitor.config.*` or signing keys. A server-rendered app is not yet
|
|
116
|
+
supported as a phone app: it needs a separate static client first.
|
|
117
|
+
|
|
118
|
+
## Adoption
|
|
119
|
+
|
|
120
|
+
- Inventory the real files before changing project contracts: the installed
|
|
121
|
+
`next` version in the lockfile, `app/` or `pages/`, `next.config.*` (`output`,
|
|
122
|
+
`basePath`, `distDir`, `experimental`), `middleware.*`/`proxy.*`, the auth
|
|
123
|
+
library and its environment names, the ORM and its migration commands, and
|
|
124
|
+
the real `dev`, `build`, `start`, `lint` and `test` scripts.
|
|
125
|
+
- Identify the package manager from the lockfile and replace every proposed
|
|
126
|
+
`npm` line when the project uses pnpm, Yarn or Bun. Next.js 16 removed
|
|
127
|
+
`next lint`; if the `lint` script is missing, remove that Verification line
|
|
128
|
+
instead of inventing one, and add the project's real test command when it
|
|
129
|
+
has one.
|
|
130
|
+
- Replace the readiness path when `/` is not publicly reachable, a `basePath`
|
|
131
|
+
is set, or a dedicated health route exists. Replace the Serve line for
|
|
132
|
+
`output: "standalone"`, a custom server, or `output: "export"`.
|
|
133
|
+
- A custom Next.js server built on Express is a project-owned decision: keep
|
|
134
|
+
this piece and describe that server's real commands in the project's own
|
|
135
|
+
sections.
|
|
136
|
+
|
|
137
|
+
## Workspace setup
|
|
138
|
+
|
|
139
|
+
- Prepare `Install dependencies` with `nodejs` when `package.json` exists: `npm` `install`
|
|
140
|
+
|
|
141
|
+
## Outputs
|
|
142
|
+
|
|
143
|
+
### Target `app`: Run Next.js app
|
|
144
|
+
|
|
145
|
+
- Default.
|
|
146
|
+
- Mode: `interactive`
|
|
147
|
+
- Runtimes: `nodejs`
|
|
148
|
+
- Run `Develop`: `npm` `run` `dev` `--` `--hostname` `{host}` `--port` `{port}`
|
|
149
|
+
|
|
150
|
+
#### Presentation
|
|
151
|
+
|
|
152
|
+
- Kind: `web`
|
|
153
|
+
- Preferred port: `3000`
|
|
154
|
+
- URL path: `/`
|
|
155
|
+
- Ready when: `GET` `/` returns `200`
|
|
156
|
+
|
|
157
|
+
## Verification
|
|
158
|
+
|
|
159
|
+
- Verify `lint`: `npm` `run` `lint`
|
|
160
|
+
- Verify `build`: `npm` `run` `build`
|
|
161
|
+
|
|
162
|
+
## Deployment
|
|
163
|
+
|
|
164
|
+
- Runtimes: `nodejs`
|
|
165
|
+
- Recreate on restore: `node_modules` `.next/cache`
|
|
166
|
+
- Ready when: `GET` `/` returns `200`
|
|
167
|
+
- Prepare `Install dependencies`: `npm` `ci`
|
|
168
|
+
- Build `Build`: `npm` `run` `build`
|
|
169
|
+
- Serve `Start`: `sh` `-c` `exec npm start -- --hostname "$HOST"`
|
|
170
|
+
|
|
171
|
+
## Deslop
|
|
172
|
+
|
|
173
|
+
- Keep data fetching in Server Components, route handlers and Server Actions
|
|
174
|
+
where the router supports it; remove client-side fetch wrappers that only
|
|
175
|
+
duplicate a server read.
|
|
176
|
+
- Keep `"use client"` boundaries as low in the tree as possible and do not mark
|
|
177
|
+
whole layouts as client components to reach one interactive widget.
|
|
178
|
+
- Use the framework's `Link`, `Image`, `Script`, metadata and font facilities
|
|
179
|
+
instead of hand-written equivalents.
|
|
180
|
+
- Remove abandoned starter content, unused route segments and duplicate
|
|
181
|
+
environment readers only when routes, redirects and tests stay unchanged.
|
package/stacks/pieces/nodejs.md
CHANGED
|
@@ -41,9 +41,21 @@ Node.js package, command, module, dependency, and test conventions.
|
|
|
41
41
|
`package.json` and `package-lock.json` stay unchanged; Verify resolves each
|
|
42
42
|
package from the application root and fails unless it resolves to its
|
|
43
43
|
connected source root. An ordinary `npm ci` restores the published packages.
|
|
44
|
+
- Publishing a library to npm: the host-owned `## Packaging` section declares
|
|
45
|
+
the package (`npm` packer, its Workdir, `Version from: package.json`) only
|
|
46
|
+
when a publishing target is added; the host builds with `npm pack` from the
|
|
47
|
+
saved commit and owns tags, credentials and uploads. Keep `name`, `version`,
|
|
48
|
+
`license`, `files` (or `.npmignore`) and an `exports`/`main` entry correct in
|
|
49
|
+
`package.json`; never commit tarballs, tokens or `.npmrc` credentials, and
|
|
50
|
+
remove `"private": true` only for a package that is really published. A
|
|
51
|
+
build step before packing (TypeScript, bundling) is a declared Build command
|
|
52
|
+
such as `npm run build`, not a `prepublishOnly` script. A project using
|
|
53
|
+
Changesets or release-please keeps that tool and declares
|
|
54
|
+
`Version from: external`.
|
|
44
55
|
- Long-running web processes accept their listen host and port from arguments
|
|
45
56
|
or the environment rather than hard-coding them, and fail if the port is
|
|
46
|
-
taken instead of silently choosing another.
|
|
57
|
+
taken instead of silently choosing another. For Express or Next.js select
|
|
58
|
+
`express` or `nextjs`; that piece owns the framework traps.
|
|
47
59
|
|
|
48
60
|
## Adoption
|
|
49
61
|
|
package/stacks/pieces/python.md
CHANGED
|
@@ -42,13 +42,26 @@ Python package, module, callable, dependency, and test conventions.
|
|
|
42
42
|
PEP 610 `direct_url.json` is editable with the source root's `file:` URL and
|
|
43
43
|
that its modules import from there. Do not use `uv sync`, which needs tracked
|
|
44
44
|
`[tool.uv.sources]` and lockfile changes.
|
|
45
|
+
- Publishing a library to PyPI: the host-owned `## Packaging` section declares
|
|
46
|
+
the package (`python-dist` packer, `Runtimes: python`, its `dist` Output,
|
|
47
|
+
`Version from: pyproject.toml`) only when a publishing target is added; the
|
|
48
|
+
host builds the sdist and wheel from the saved commit and owns tags,
|
|
49
|
+
credentials and uploads. The build runs in a clean copy where `build` is
|
|
50
|
+
not installed, and managed Pythons refuse a bare `pip install` (PEP 668), so
|
|
51
|
+
a plain `python3 -m build` fails. The package installs its own throwaway
|
|
52
|
+
tools: Prepare `python3 -m venv .build-tools`, Prepare
|
|
53
|
+
`.build-tools/bin/python -m pip install --quiet build`, Build
|
|
54
|
+
`.build-tools/bin/python -m build`; add `.build-tools/` to `.gitignore`. Keep a PEP 621
|
|
55
|
+
`[project]` table with a static `version`, `readme`, `license` and
|
|
56
|
+
`requires-python` so `twine check --strict` passes; versions use PEP 440
|
|
57
|
+
(`1.5.0rc1`). Never commit `dist/`, tokens or `.pypirc`. A project with a
|
|
58
|
+
dynamic version (setuptools-scm, hatch-vcs) declares
|
|
59
|
+
`Version from: external`.
|
|
45
60
|
- Running a web process: bind the supplied listen host and port, trust forwarded
|
|
46
61
|
headers only from a loopback proxy, and read secrets from the environment.
|
|
47
|
-
Django
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
proxy, and read `SECRET_KEY` from the environment. Flask uses Werkzeug's
|
|
51
|
-
`ProxyFix`; Uvicorn uses `--proxy-headers --forwarded-allow-ips 127.0.0.1`.
|
|
62
|
+
For Django select `django`; its piece owns the framework traps. Flask uses
|
|
63
|
+
Werkzeug's `ProxyFix`; Uvicorn uses `--proxy-headers --forwarded-allow-ips
|
|
64
|
+
127.0.0.1`.
|
|
52
65
|
|
|
53
66
|
## Connected development
|
|
54
67
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Stack piece: rails-mysql
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Rails MySQL connection, Active Record migration, and database environment conventions.
|
|
6
|
+
|
|
7
|
+
## Requires
|
|
8
|
+
|
|
9
|
+
- `rails`
|
|
10
|
+
- `mysql`
|
|
11
|
+
|
|
12
|
+
## Conflicts
|
|
13
|
+
|
|
14
|
+
- `rails-postgresql`
|
|
15
|
+
- `rails-sqlite`
|
|
16
|
+
|
|
17
|
+
## Environment defaults
|
|
18
|
+
|
|
19
|
+
- Default `DB_HOST`: `127.0.0.1`
|
|
20
|
+
- Default `DB_PORT`: `3306`
|
|
21
|
+
- Default `DB_DATABASE`: `rails`
|
|
22
|
+
- Default `DB_USERNAME`: `root`
|
|
23
|
+
|
|
24
|
+
## Resources
|
|
25
|
+
|
|
26
|
+
```json genesis-resource
|
|
27
|
+
{
|
|
28
|
+
"id": "database",
|
|
29
|
+
"kind": "mysql",
|
|
30
|
+
"environmentAlternatives": [
|
|
31
|
+
{
|
|
32
|
+
"bindings": {
|
|
33
|
+
"database": "DB_DATABASE",
|
|
34
|
+
"host": "DB_HOST",
|
|
35
|
+
"password": "DB_PASSWORD",
|
|
36
|
+
"port": "DB_PORT",
|
|
37
|
+
"username": "DB_USERNAME"
|
|
38
|
+
},
|
|
39
|
+
"allowEmpty": ["password"],
|
|
40
|
+
"preferred": true
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"optionalBindings": {
|
|
44
|
+
"testDatabase": "TEST_DB_NAME"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Guidance
|
|
50
|
+
|
|
51
|
+
- `rails new -d mysql` (adapter `mysql2`) or `-d trilogy` hard-codes database
|
|
52
|
+
names. Make `config/database.yml` read the resource names: under `default`,
|
|
53
|
+
`host: <%= ENV.fetch("DB_HOST", "127.0.0.1") %>`,
|
|
54
|
+
`port: <%= ENV.fetch("DB_PORT", 3306) %>`,
|
|
55
|
+
`username: <%= ENV["DB_USERNAME"] %>`, `password: <%= ENV["DB_PASSWORD"] %>`;
|
|
56
|
+
and `database: <%= ENV["DB_DATABASE"] %>` for development and the
|
|
57
|
+
production primary. Point `test` at
|
|
58
|
+
`<%= ENV.fetch("TEST_DB_NAME", "<app>_test") %>`, never at the development
|
|
59
|
+
or production database.
|
|
60
|
+
- Keep `encoding: utf8mb4`. `mysql2` compiles against the MySQL client
|
|
61
|
+
library; `trilogy` (Rails 7.1+) is pure Ruby and avoids it. Do not switch an
|
|
62
|
+
existing app's adapter without testing it.
|
|
63
|
+
- `bin/rails test` purges the test database whenever its schema is out of
|
|
64
|
+
date by dropping and recreating it, so the user needs `CREATE` and `DROP`
|
|
65
|
+
on that database name even when `TEST_DB_NAME` names it.
|
|
66
|
+
- Rails 8 production declares separate `cache`, `queue` and `cable`
|
|
67
|
+
databases. When only one database is supplied, follow the Solid Cache, Solid
|
|
68
|
+
Queue and Solid Cable single-database instructions (their schemas become
|
|
69
|
+
ordinary migrations and their `connects_to` settings are removed) instead of
|
|
70
|
+
inventing extra database names.
|
|
71
|
+
- Use the inherited Rails migration and seed guidance. Keep connection,
|
|
72
|
+
integration and payment records in this database through Active Record
|
|
73
|
+
migrations and transactions; test uniqueness and concurrent updates on MySQL
|
|
74
|
+
itself.
|
|
75
|
+
|
|
76
|
+
## Adoption
|
|
77
|
+
|
|
78
|
+
- Confirm the adapter, every environment's database, username, password, host
|
|
79
|
+
and port expressions in `config/database.yml`, and whether `DATABASE_URL` is
|
|
80
|
+
read, before declaring readiness or connecting. Align the project Resource
|
|
81
|
+
bindings with the names the file actually reads.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Stack piece: rails-postgresql
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Rails PostgreSQL connection, Active Record migration, and database environment conventions.
|
|
6
|
+
|
|
7
|
+
## Requires
|
|
8
|
+
|
|
9
|
+
- `rails`
|
|
10
|
+
- `postgresql`
|
|
11
|
+
|
|
12
|
+
## Conflicts
|
|
13
|
+
|
|
14
|
+
- `rails-mysql`
|
|
15
|
+
- `rails-sqlite`
|
|
16
|
+
|
|
17
|
+
## Environment defaults
|
|
18
|
+
|
|
19
|
+
- Default `DB_HOST`: `127.0.0.1`
|
|
20
|
+
- Default `DB_PORT`: `5432`
|
|
21
|
+
- Default `DB_DATABASE`: `rails`
|
|
22
|
+
- Default `DB_USERNAME`: `postgres`
|
|
23
|
+
|
|
24
|
+
## Resources
|
|
25
|
+
|
|
26
|
+
```json genesis-resource
|
|
27
|
+
{
|
|
28
|
+
"id": "database",
|
|
29
|
+
"kind": "postgresql",
|
|
30
|
+
"environmentAlternatives": [
|
|
31
|
+
{
|
|
32
|
+
"bindings": {
|
|
33
|
+
"database": "DB_DATABASE",
|
|
34
|
+
"host": "DB_HOST",
|
|
35
|
+
"password": "DB_PASSWORD",
|
|
36
|
+
"port": "DB_PORT",
|
|
37
|
+
"username": "DB_USERNAME"
|
|
38
|
+
},
|
|
39
|
+
"allowEmpty": ["password"],
|
|
40
|
+
"preferred": true
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"optionalBindings": {
|
|
44
|
+
"testDatabase": "TEST_DB_NAME"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Guidance
|
|
50
|
+
|
|
51
|
+
- `rails new -d postgresql` hard-codes database names and reads only a
|
|
52
|
+
production password variable. Make `config/database.yml` read the resource
|
|
53
|
+
names: under `default`, `host: <%= ENV.fetch("DB_HOST", "127.0.0.1") %>`,
|
|
54
|
+
`port: <%= ENV.fetch("DB_PORT", 5432) %>`,
|
|
55
|
+
`username: <%= ENV["DB_USERNAME"] %>`, `password: <%= ENV["DB_PASSWORD"] %>`;
|
|
56
|
+
and `database: <%= ENV["DB_DATABASE"] %>` for development and the
|
|
57
|
+
production primary. Point `test` at
|
|
58
|
+
`<%= ENV.fetch("TEST_DB_NAME", "<app>_test") %>`, never at the development
|
|
59
|
+
or production database.
|
|
60
|
+
- `bin/rails test` purges the test database whenever its schema is out of
|
|
61
|
+
date by dropping and recreating it, so the role needs `CREATEDB` (and must
|
|
62
|
+
own the database) even when `TEST_DB_NAME` names it.
|
|
63
|
+
- After loading fixtures, Rails checks their foreign keys
|
|
64
|
+
(`verify_foreign_keys_for_fixtures`, on by default) by updating
|
|
65
|
+
`pg_catalog.pg_constraint`, which only a superuser may do. With an ordinary
|
|
66
|
+
`CREATEDB` role every fixture test fails with `permission denied for table
|
|
67
|
+
pg_constraint`; set `config.active_record.verify_foreign_keys_for_fixtures =
|
|
68
|
+
false` in `config/environments/test.rb` rather than granting superuser.
|
|
69
|
+
- Rails 8 production declares separate `cache`, `queue` and `cable`
|
|
70
|
+
databases. When only one database is supplied, follow the Solid Cache, Solid
|
|
71
|
+
Queue and Solid Cable single-database instructions (their schemas become
|
|
72
|
+
ordinary migrations and their `connects_to` settings are removed) instead of
|
|
73
|
+
inventing extra database names.
|
|
74
|
+
- The `pg` gem compiles against libpq unless the locked version ships a
|
|
75
|
+
precompiled gem for the platform.
|
|
76
|
+
- Use the inherited Rails migration and seed guidance. Keep connection,
|
|
77
|
+
integration and payment records in this database through Active Record
|
|
78
|
+
migrations and transactions; test uniqueness and concurrent updates on
|
|
79
|
+
PostgreSQL itself.
|
|
80
|
+
|
|
81
|
+
## Adoption
|
|
82
|
+
|
|
83
|
+
- Confirm the adapter, every environment's database, username, password, host
|
|
84
|
+
and port expressions in `config/database.yml`, and whether `DATABASE_URL` is
|
|
85
|
+
read, before declaring readiness or connecting. Align the project Resource
|
|
86
|
+
bindings with the names the file actually reads.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Stack piece: rails-sqlite
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Rails SQLite connection, Active Record migration, and database filename conventions.
|
|
6
|
+
|
|
7
|
+
## Requires
|
|
8
|
+
|
|
9
|
+
- `rails`
|
|
10
|
+
- `sqlite`
|
|
11
|
+
|
|
12
|
+
## Conflicts
|
|
13
|
+
|
|
14
|
+
- `rails-mysql`
|
|
15
|
+
- `rails-postgresql`
|
|
16
|
+
|
|
17
|
+
## Resources
|
|
18
|
+
|
|
19
|
+
```json genesis-resource
|
|
20
|
+
{
|
|
21
|
+
"id": "database",
|
|
22
|
+
"kind": "sqlite",
|
|
23
|
+
"environmentAlternatives": [
|
|
24
|
+
{
|
|
25
|
+
"bindings": {
|
|
26
|
+
"database": "DB_DATABASE"
|
|
27
|
+
},
|
|
28
|
+
"preferred": true
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Guidance
|
|
35
|
+
|
|
36
|
+
- `rails new` (SQLite is the default) writes repository-relative files under
|
|
37
|
+
`storage/`, and Rails 8.1 leaves the production files unset. Make the
|
|
38
|
+
development and production primary read the supplied filename with the
|
|
39
|
+
generated name as fallback, for example
|
|
40
|
+
`database: <%= ENV.fetch("DB_DATABASE", "storage/development.sqlite3") %>`.
|
|
41
|
+
A bare `ENV.fetch("DB_DATABASE")` raises while `database.yml` loads and
|
|
42
|
+
breaks generators and asset builds that run without the variable. Keep `test`
|
|
43
|
+
on its own file such as `storage/test.sqlite3`.
|
|
44
|
+
- Rails 8 production also declares `cache`, `queue` and `cable` SQLite
|
|
45
|
+
databases. Keep them next to the primary file, for example
|
|
46
|
+
`<%= File.join(File.dirname(ENV.fetch("DB_DATABASE", "storage/production.sqlite3")), "production_cache.sqlite3") %>`,
|
|
47
|
+
so they persist with it; never leave them in a disposable release directory.
|
|
48
|
+
- Do not replace a supplied filename with a repository-relative default or
|
|
49
|
+
delete an existing file. `bin/rails db:prepare` creates a missing file and
|
|
50
|
+
its schema and migrates an existing one.
|
|
51
|
+
- The `sqlite3` gem normally installs a precompiled native gem; a source build
|
|
52
|
+
needs the SQLite headers. Use the inherited Rails migration and seed
|
|
53
|
+
guidance and test concurrent writes on SQLite itself.
|
|
54
|
+
|
|
55
|
+
## Adoption
|
|
56
|
+
|
|
57
|
+
- Read `config/database.yml` for every environment's filename, including the
|
|
58
|
+
Rails 8 cache, queue and cable files, and preserve existing data: snapshot
|
|
59
|
+
it before moving to a supplied filename. Do not switch an existing app to an
|
|
60
|
+
empty database.
|