@devdogsuga/devtools 0.1.50 → 0.1.51-next.527
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 +81 -7
- package/bin/with-env.mjs +17 -0
- package/dist/app-registry-BoAnenqC.js +38 -0
- package/dist/{cli-t3gWyy3w.js → cli-D4LUUxUR.js} +2286 -718
- package/dist/launch.js +23 -11
- package/dist/load-Cp8AMERM.js +640 -0
- package/dist/load-Czhayrsk.js +2 -0
- package/dist/{menu-DYQ-Dd-O.js → menu-DjE4EZKO.js} +475 -178
- package/dist/{failure-log-DOt6E3hS.js → root-CsocfxnK.js} +104 -5
- package/dist/session-CmDxHEMn.js +2 -0
- package/dist/session-rbONwFvY.js +431 -0
- package/dist/{stack-C_50FafG.js → stack-7Lbym6Wq.js} +2 -3
- package/dist/stack-7qA2UP9g.js +2 -0
- package/dist/supabase-project-BoJKMCxL.js +766 -0
- package/dist/{telemetry-C07-ioHm.js → telemetry-BKFDtzXI.js} +8 -9
- package/dist/telemetry.js +1 -1
- package/dist/with-env.js +370 -0
- package/dist/worker-env-CAFmquhW.js +36 -0
- package/dist/wrangler-env-BrlNe4pm.js +34 -0
- package/env.ts +1 -1
- package/package.json +11 -20
- package/dist/local-env-BuHU5Ckd.js +0 -357
- package/dist/local-env-MqH18s-N.js +0 -2
- package/dist/peers-DvUH5VxX.js +0 -354
- package/dist/root-CjPWNkBu.js +0 -99
- package/dist/stack-o1Kml3V0.js +0 -2
- package/dist/supabase-project-C93xRFkN.js +0 -436
package/README.md
CHANGED
|
@@ -56,11 +56,12 @@ command path (deprecated ones marked), for tools that check what a page shows.
|
|
|
56
56
|
|
|
57
57
|
The `db` and `cf` namespaces are gone: `supabase`, `wrangler`, `drizzle-kit`
|
|
58
58
|
and `psql` plus package scripts (`types:db`, `types:drizzle`, `types:cf`,
|
|
59
|
-
`preview`) replace them. `run`
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
`
|
|
63
|
-
|
|
59
|
+
`preview`) replace them. The deprecated `run` alias is gone too (TASK-404):
|
|
60
|
+
`pnpm -r run <task>` runs a task in every package and `pnpm -F <app> <task>`
|
|
61
|
+
in one. The retired `db`, `cf`, `gen`, `emails`, `grant-root`, `preset` and
|
|
62
|
+
`run` names are refused with where they went (`preset apply-migrations` is now
|
|
63
|
+
`apply-migrations`, and so on). Inside a product repository (below) `db` is
|
|
64
|
+
the product's own command.
|
|
64
65
|
|
|
65
66
|
What always needs production secrets is not here. `deploy`, `env
|
|
66
67
|
pull|push|audit` and `planner` are in `@devdogsuga/backstage`
|
|
@@ -92,6 +93,79 @@ name `devdogs-monorepo` or `backstage`; the layout code is
|
|
|
92
93
|
`pnpm exec supabase` and `wrangler` run inside DevDogsUGA's workspace, so
|
|
93
94
|
`devdogsuga/` needs its own `pnpm install` before the commands that use them.
|
|
94
95
|
|
|
96
|
+
## Product repositories
|
|
97
|
+
|
|
98
|
+
A repository with a `devtools.config.json` at its root is a **product** (DogDays, DogPack): devtools
|
|
99
|
+
reads the file and serves a smaller command set that needs no tiers, no env registry and no workspace.
|
|
100
|
+
DogPack has no `package.json`, so it runs the published CLI directly:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
npx @devdogsuga/devtools@next setup
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
| Command | What it does |
|
|
107
|
+
| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
108
|
+
| `setup [--local \| --hosted]` | Writes `.env` from `.env.example`; starts the Docker stack (or takes your own hosted project's URL, keys and session-pooler `DB_URL`); `db sync`; the types; then `oauth`. |
|
|
109
|
+
| `db sync [--rebuild] [--yes]` | Makes your development database match `supabase/schemas/`. Never resets it; `--rebuild` is the explicit reset (local only) and registers sign in again afterwards. |
|
|
110
|
+
| `db types [--download] [--pack <file>]` | Generates the TypeScript types or Dart models from your database, or downloads the ones CI built for your exact schema hash. `--pack` writes the release asset (CI). |
|
|
111
|
+
| `db hash` | Prints the schema hash that names the generated types. |
|
|
112
|
+
| `dev-data [--member <email\|id>]` | Runs the product's `devData.file` SQL, in one transaction, as the member who last signed in with DevDogs. Refuses the product's production project. |
|
|
113
|
+
| `oauth` | "Sign in with DevDogs" on your database (the same wizard as the platform's). |
|
|
114
|
+
| `doctor` | Docker, the pinned Supabase CLI, `.env`, the database, whether the types match the schema. |
|
|
115
|
+
| `supabase <args>` | The Supabase CLI at the version the product pins. |
|
|
116
|
+
| `check env-example` | CI: `.env.example` holds public values only (it ships in the app). |
|
|
117
|
+
|
|
118
|
+
How it works, in short:
|
|
119
|
+
|
|
120
|
+
- **Schemas, not migrations.** Contributors edit `supabase/schemas/*.sql`. `db sync` asks the Supabase CLI
|
|
121
|
+
(`db schema declarative sync --no-apply`) to diff them against a git-ignored `supabase/migrations/` that
|
|
122
|
+
records what this database has had applied, writes the difference as a new migration, and applies it
|
|
123
|
+
(`migration up --local`, or `db push --db-url` for a hosted project). A change that drops a table or column
|
|
124
|
+
needs `--yes`. It then regenerates the types (and leaves them alone when nothing changed and they are current).
|
|
125
|
+
On a hosted project, a machine with no record (a second laptop, a deleted `supabase/migrations/`) first
|
|
126
|
+
restores it from the project's own history table (`migration fetch --db-url`), so the diff is not taken
|
|
127
|
+
against an empty database.
|
|
128
|
+
- **Types are never committed.** `db types` writes them to the path in the config, which is git-ignored.
|
|
129
|
+
The schema hash covers the sorted schema paths, their LF-normalised contents and the generator version (the
|
|
130
|
+
pinned CLI, or supadart); CI uploads a `<product>-types-<hash>.tgz` asset to a rolling `generated-types`
|
|
131
|
+
release, and `db types --download` fetches the one for your hash. No match: it says so and points at `setup`.
|
|
132
|
+
- **Two env files.** `.env` is public and read by the app (`flutter run --dart-define-from-file=.env`);
|
|
133
|
+
`.env.tooling` is git-ignored and holds `DB_URL`, `SECRET_KEY`, the target (`local` or `hosted`) and the
|
|
134
|
+
"Sign in with DevDogs" client id and secret (`OAUTH_CLIENT_ID`, `OAUTH_CLIENT_SECRET`, which
|
|
135
|
+
`db sync --rebuild` registers again). Nothing is written to `.env.local` in a product repo. `setup` (both files) and
|
|
136
|
+
`oauth` (the tooling file) check that they are git-ignored and add them to the repo's `.gitignore`
|
|
137
|
+
when they are not (Flutter's default ignore file leaves them out).
|
|
138
|
+
- **The pinned CLI.** devtools finds `supabase` in `node_modules/.bin` or on PATH when its version is the
|
|
139
|
+
pin, and otherwise runs `npx --yes supabase@<pin>`.
|
|
140
|
+
- **A hosted project** needs custom OAuth providers turned on and the app's return addresses allowed.
|
|
141
|
+
`setup` does both through the Management API when `SUPABASE_ACCESS_TOKEN` is set, and prints the two
|
|
142
|
+
dashboard steps when it is not.
|
|
143
|
+
- **No terminal.** `setup` takes `DEVTOOLS_SUPABASE_URL`, `DEVTOOLS_SUPABASE_PUBLISHABLE_KEY`,
|
|
144
|
+
`DEVTOOLS_SUPABASE_SECRET_KEY` and `DEVTOOLS_DB_URL` for a hosted project, and registers sign in from
|
|
145
|
+
`DEVDOGS_OAUTH_CLIENT_ID` / `DEVDOGS_OAUTH_CLIENT_SECRET` instead of opening a browser.
|
|
146
|
+
|
|
147
|
+
```jsonc
|
|
148
|
+
// devtools.config.json
|
|
149
|
+
{
|
|
150
|
+
"product": "dogpack", // lowercase id; names the generated-types assets
|
|
151
|
+
"name": "DogPack",
|
|
152
|
+
"supabase": {
|
|
153
|
+
"version": "2.117.0", // the CLI pin; part of the types hash
|
|
154
|
+
"schemas": ["dogpack"], // schemas the generated types cover
|
|
155
|
+
// "dir": "supabase"
|
|
156
|
+
},
|
|
157
|
+
"types": { "kind": "supadart", "out": "lib/generated" }, // or { "kind": "typescript", "out": "src/database.types.ts" }
|
|
158
|
+
"generatedTypes": { "repo": "DevDogsUGA/DogPack" }, // where `db types --download` looks
|
|
159
|
+
"oauth": { "redirectUris": ["dev.dogpack://login-callback"] },
|
|
160
|
+
"devData": { "file": "supabase/dev-data.sql" }, // reads current_setting('devtools.member_id')
|
|
161
|
+
"production": { "projects": ["dogpack"] }, // refs and vanity names devtools must never touch
|
|
162
|
+
"runHint": "flutter run --dart-define-from-file=.env",
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The code is in `src/product/`; `src/active.ts` picks the tree, and `src/launch.ts` switches to it before any
|
|
167
|
+
tier is resolved.
|
|
168
|
+
|
|
95
169
|
## Telemetry disclosure
|
|
96
170
|
|
|
97
171
|
This CLI reports its own crashes to Sentry (see `src/telemetry.ts`), on by
|
|
@@ -108,10 +182,10 @@ default, in both `pnpm devtools` and `devtools-ci`:
|
|
|
108
182
|
no `Sentry.init()` call happens: no network request, no console output.
|
|
109
183
|
- **What's scrubbed**: this CLI touches local `.env` files, so every event
|
|
110
184
|
passes through
|
|
111
|
-
`@devdogsuga/telemetry`'s shared scrubbers before it leaves the process —
|
|
185
|
+
`@devdogsuga/sdk/telemetry`'s shared scrubbers before it leaves the process —
|
|
112
186
|
file paths reduced to basenames, email addresses redacted, and
|
|
113
187
|
token/secret-shaped values stripped out of messages, breadcrumbs, and
|
|
114
|
-
stack frames. See
|
|
188
|
+
stack frames. See `packages/sdk/src/telemetry/scrub.ts` for exactly what each
|
|
115
189
|
scrubber matches.
|
|
116
190
|
|
|
117
191
|
## Layout
|
package/bin/with-env.mjs
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The `with-env` bin: loads a tier's env files around one command.
|
|
3
|
+
//
|
|
4
|
+
// with-env [--tier <tier>] <command> [args...]
|
|
5
|
+
// with-env -c '<shell command>'
|
|
6
|
+
// with-env --worker <app> -- <command> [args...]
|
|
7
|
+
//
|
|
8
|
+
// It used to be `@devdogsuga/env`'s bin and ran TypeScript source through tsx;
|
|
9
|
+
// the env tooling moved into devtools, so it ships built like the other bin.
|
|
10
|
+
// tsx stays registered because `--worker` imports an app's TypeScript env
|
|
11
|
+
// manifest. A `node` shebang is what package-manager bin shims handle most
|
|
12
|
+
// reliably (notably the generated .cmd on Windows), and resolving tsx through
|
|
13
|
+
// this package's own dependencies avoids relying on it being on PATH.
|
|
14
|
+
import { register } from "tsx/esm/api";
|
|
15
|
+
|
|
16
|
+
register();
|
|
17
|
+
await import("../dist/with-env.js");
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
//#region ../cli-core/src/env-runtime/app-registry.ts
|
|
6
|
+
/**
|
|
7
|
+
* Loads an app's own manifest so `with-env --worker` can scope the Worker env.
|
|
8
|
+
*
|
|
9
|
+
* The registry fills as a side effect of importing the manifest, and it must
|
|
10
|
+
* be the SAME `@devdogsuga/sdk/env` instance the manifest's `declare()` calls hit,
|
|
11
|
+
* which is the copy resolved from the manifest, not this package's own
|
|
12
|
+
* (running from source under tsx, those are different files). So the registry
|
|
13
|
+
* is read back from that copy.
|
|
14
|
+
*/
|
|
15
|
+
/** `src/env.ts`, then `env.ts`; both present in one package is an error. */
|
|
16
|
+
function findManifest(dir) {
|
|
17
|
+
const inSrc = join(dir, "src", "env.ts");
|
|
18
|
+
const atRoot = join(dir, "env.ts");
|
|
19
|
+
if (existsSync(inSrc) && existsSync(atRoot)) throw new Error(`${dir} has BOTH src/env.ts and env.ts. One package gets one manifest.`);
|
|
20
|
+
return existsSync(inSrc) ? inSrc : existsSync(atRoot) ? atRoot : null;
|
|
21
|
+
}
|
|
22
|
+
/** Needs a tsx-enabled process, which the `with-env` bin always is. */
|
|
23
|
+
async function loadAppRegistry(dir) {
|
|
24
|
+
const manifest = findManifest(dir);
|
|
25
|
+
if (!manifest) throw new Error(`no env manifest (src/env.ts or env.ts) in ${dir}.`);
|
|
26
|
+
const previous = process.env.SKIP_ENV_VALIDATION;
|
|
27
|
+
process.env.SKIP_ENV_VALIDATION = "1";
|
|
28
|
+
try {
|
|
29
|
+
await import(pathToFileURL(manifest).href);
|
|
30
|
+
} finally {
|
|
31
|
+
if (previous === void 0) delete process.env.SKIP_ENV_VALIDATION;
|
|
32
|
+
else process.env.SKIP_ENV_VALIDATION = previous;
|
|
33
|
+
}
|
|
34
|
+
const resolved = createRequire(manifest).resolve("@devdogsuga/sdk/env");
|
|
35
|
+
return await import(pathToFileURL(resolved).href);
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { findManifest, loadAppRegistry };
|