@sidebase/base-config 0.2.0 → 0.2.2

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/config.d.ts CHANGED
@@ -1,19 +1,16 @@
1
- import { C as CreateSidebaseEslintOptions } from './shared/base-config.CuUhyvQo.js';
1
+ import { C as CreateSidebaseEslintOptions } from './shared/base-config.BoberVUk.js';
2
2
 
3
3
  /**
4
- * Version-baseline profile, named for the framework AND its major so two majors can
5
- * coexist during a migration: the manifest declares one profile per major with its own
6
- * `detect.majorIs`, and each repo detects the one matching its own Nuxt version.
4
+ * Version-baseline profile, named for the framework and its major so two majors can
5
+ * coexist during a migration.
7
6
  *
8
- * The name MUST match a `versionProfiles` key in the preset chain. The CLI resolves the
9
- * baseline with `versionProfiles?.[profile] ?? {}`, so a name nothing declares reconciles
10
- * NOTHING, silently. `scripts/validate-presets.mjs` fails the build on that mismatch.
7
+ * An unknown name reconciles nothing, silently. `scripts/validate-presets.mjs` fails
8
+ * the build on that mismatch.
11
9
  */
12
10
  type Profile = "nuxt-4";
13
11
  /**
14
- * Optional CI knobs (`config.ci.*`) the nuxt-app preset understands: the job
15
- * toggles. Keys mirror the manifest's `ci.*` `configKeys`; the consistency test
16
- * in `test/config.test.ts` proves they stay in lockstep.
12
+ * CI job knobs (`config.ci.*`). Keys mirror the manifest's `ci.*` `configKeys`, and
13
+ * `test/config.test.ts` proves the two stay in lockstep.
17
14
  */
18
15
  interface NuxtBaseCiConfig {
19
16
  /** Include the `pnpm test` job. */
@@ -21,22 +18,19 @@ interface NuxtBaseCiConfig {
21
18
  /** Include the e2e job + postgres service. */
22
19
  e2e?: boolean;
23
20
  /**
24
- * System packages apt-installed in the `test` and `e2e` jobs before
25
- * `pnpm install`, for a binary the suite needs that `ubuntu-latest` does not
26
- * ship (the motivating case: `libxml2-utils` for `xmllint`). Empty by default,
27
- * which renders the install step inert rather than absent. Package names only:
28
- * each element is metacharacter-checked, then the joined string is re-validated
29
- * by the manifest pattern, because the rendered `run:` line is deliberately
30
- * unquoted so word splitting reaches apt-get.
21
+ * Packages apt-installed in the `test` and `e2e` jobs, for a binary the suite needs
22
+ * that `ubuntu-latest` lacks. Empty renders the install step inert, not absent.
23
+ *
24
+ * Package names only: the rendered `run:` line is unquoted so word splitting reaches
25
+ * apt-get, so every element is metacharacter-checked.
31
26
  */
32
27
  aptPackages?: string[];
33
28
  }
34
29
  /**
35
- * Optional runtime version pins (`config.versions.*`). `node` feeds every
36
- * render (`ci.yml`, the Dockerfile, the upgrade-PR workflow); `pnpm` feeds the
37
- * Dockerfile only. CI takes its pnpm from `package.json#packageManager`, the
38
- * single reconciled source, so it is never passed to `pnpm/action-setup`.
39
- * Defaults come from the version baseline (node 24.13.0, pnpm 10.28.1).
30
+ * Runtime version pins (`config.versions.*`). `node` feeds every render (`ci.yml`,
31
+ * the Dockerfile, the upgrade workflow); `pnpm` feeds the Dockerfile only, because CI
32
+ * takes pnpm from `package.json#packageManager`. Defaults come from the version
33
+ * baseline (node 24.13.0, pnpm 10.28.1).
40
34
  */
41
35
  interface NuxtBaseVersionsConfig {
42
36
  /** Node version for CI jobs, the Docker base image, and the upgrade workflow. */
@@ -52,16 +46,15 @@ interface NuxtBaseVersionsConfig {
52
46
  */
53
47
  interface NuxtBaseDockerConfig {
54
48
  /**
55
- * Project-owned apt packages for the production stage, ON TOP of the baked-in
56
- * baseline (`openssl`: the Prisma query engine generated in the build stage
57
- * dynamically links libssl3, which slim images do not ship).
49
+ * Apt packages for the production stage, on top of the baked-in `openssl`, which is
50
+ * always installed because the Prisma query engine links libssl3 and slim images do
51
+ * not ship it.
58
52
  */
59
53
  aptPackages?: string[];
60
54
  /**
61
- * Raw Dockerfile text injected in the build stage BEFORE `pnpm install`, e.g.
62
- * a `COPY ./vendor ./vendor` a repo needs present at install time. Lands
63
- * verbatim; see the trust note below. Global installs must use `npm i -g`
64
- * (`PNPM_HOME` is not set, so `pnpm add -g` fails to find its bin dir).
55
+ * Raw Dockerfile text injected in the build stage before `pnpm install`, e.g. a
56
+ * `COPY ./vendor ./vendor` needed at install time. Lands verbatim. Global installs
57
+ * must use `npm i -g`: `PNPM_HOME` is unset, so `pnpm add -g` cannot find its bin dir.
65
58
  */
66
59
  preInstall?: string;
67
60
  /**
@@ -77,15 +70,14 @@ interface NuxtBaseDockerConfig {
77
70
  buildSteps?: string;
78
71
  /**
79
72
  * Raw Dockerfile text injected in the final stage BEFORE `CMD`, e.g. extra
80
- * `ENV`, `COPY --from`, or `RUN`. Lands verbatim. Cannot drop the fixed
81
- * `USER node` switch, which sits below it.
73
+ * `ENV`, `COPY --from`, or `RUN`. Lands verbatim. The container runs as root,
74
+ * so a repo that wants an unprivileged runtime appends its own `USER` here.
82
75
  */
83
76
  finalStage?: string;
84
77
  /**
85
78
  * The final-stage Prisma runtime block (copy the schema, install the CLI for
86
79
  * `migrate deploy`). Defaults to that block; set `""` for a repo with no
87
- * Prisma. The `USER node` switch and the `.output` ownership are FIXED outside
88
- * this knob, so an override cannot re-root the container. Lands verbatim.
80
+ * Prisma. The `.output` ownership is FIXED outside this knob. Lands verbatim.
89
81
  */
90
82
  prismaRuntime?: string;
91
83
  /**
@@ -101,25 +93,26 @@ interface NuxtBaseDockerConfig {
101
93
  startCommand?: string;
102
94
  }
103
95
  /**
104
- * Optional automation knobs (`config.automation.*`) the base preset understands:
105
- * the opt-in upgrade-PR workflow and its runtime version pins. Keys mirror the
106
- * manifest's `automation.*` `configKeys`; the consistency test in
107
- * `test/config.test.ts` proves they stay in lockstep.
96
+ * Automation knobs (`config.automation.*`) for the opt-in upgrade-PR workflow. Keys
97
+ * mirror the manifest's `automation.*` `configKeys`, checked by `test/config.test.ts`.
108
98
  */
109
99
  interface NuxtBaseAutomationConfig {
110
100
  /** Sync the weekly streamctl upgrade-PR workflow (default: off, no workflow lands). */
111
101
  upgradePr?: boolean;
102
+ /** Let upgrade PRs change GitHub Actions workflows (default: false). */
103
+ allowWorkflowUpdates?: boolean;
104
+ /** Repository secret used when workflow updates are allowed. */
105
+ prTokenSecret?: string;
112
106
  }
113
107
  /**
114
- * Optional supply-chain knobs (`config.security.*`) the base preset understands:
115
- * the pnpm install cooldown rendered into the managed `pnpm-workspace.yaml`.
108
+ * Supply-chain knobs (`config.security.*`): the pnpm install cooldown rendered into
109
+ * the managed `pnpm-workspace.yaml`.
116
110
  */
117
111
  interface NuxtBaseSecurityConfig {
118
112
  /**
119
- * Minutes a version must have been published before pnpm resolves it
120
- * (`minimumReleaseAge`). Default `"10080"` (7 days); `"0"` disables the cooldown.
121
- * A STRING because the manifest's `configKeys` has no number type, same as the
122
- * `versions.*` pins.
113
+ * Minutes a version must have been published before pnpm resolves it. Default
114
+ * `"10080"` (7 days), `"0"` disables it. A string because the manifest's
115
+ * `configKeys` has no number type, same as the `versions.*` pins.
123
116
  */
124
117
  minimumReleaseAge?: string;
125
118
  }
@@ -129,33 +122,29 @@ interface NuxtBaseSecurityConfig {
129
122
  */
130
123
  interface NuxtBasePnpmConfig {
131
124
  /**
132
- * Packages allowed to run install lifecycle scripts, ON TOP of the baked-in
133
- * baseline (`@prisma/client`, `esbuild`, `prisma`). Use this instead of
134
- * `pnpm approve-builds`, which writes to the managed file and is reverted on
135
- * the next sync.
125
+ * Packages allowed to run install lifecycle scripts, on top of the baseline
126
+ * (`@prisma/client`, `esbuild`, `prisma`). Use this instead of `pnpm approve-builds`,
127
+ * which writes to the managed file and is reverted on the next sync.
136
128
  */
137
129
  onlyBuiltDependencies?: string[];
138
130
  }
139
131
  /**
140
- * Optional editor knobs (`config.editor.*`) rendered into the managed
141
- * `.vscode/settings.json`. Only the i18n-ally source language varies across the
142
- * fleet; the locales path and key style are payload-enforced.
132
+ * Editor knobs (`config.editor.*`) rendered into the managed `.vscode/settings.json`.
133
+ * Only the i18n-ally source language varies across the fleet.
143
134
  */
144
135
  interface NuxtBaseEditorConfig {
145
136
  /**
146
- * Source locale i18n-ally translates FROM (`i18n-ally.sourceLanguage`).
147
- * Default `"de"`, the fleet majority; repos authoring in English set `"en"`.
148
- * A BCP-47-ish tag (`de`, `pt-BR`, `zh-Hans-CN`); the manifest's `pattern`
149
- * rejects anything that could break the rendered JSON string.
137
+ * Source locale i18n-ally translates from. Default `"de"`; repos authoring in
138
+ * English set `"en"`. A BCP-47-ish tag (`de`, `pt-BR`, `zh-Hans-CN`); the manifest
139
+ * pattern rejects anything that could break the rendered JSON string.
150
140
  */
151
141
  i18nSourceLanguage?: string;
152
142
  }
153
143
  /**
154
- * The typed `streamctl.config.ts` shape for the `@sidebase/base-config` payload:
155
- * the CLI-universal fields plus this payload's declared knobs (`ci`, `versions`,
156
- * `docker`, `automation`, `eslint`) with their real option types. The generic CLI only
157
- * shape-checks these against the manifest's `configKeys`, so the precise types live
158
- * here, next to the payload that owns them, and consumers keep a fully typed config.
144
+ * The typed `streamctl.config.ts` shape for this payload: the CLI-universal fields plus
145
+ * the declared knobs with their real option types. The CLI only shape-checks knobs
146
+ * against the manifest's `configKeys`, so the precise types live here, next to the
147
+ * payload that owns them, and consumers keep a fully typed config.
159
148
  */
160
149
  interface NuxtBaseConfig {
161
150
  /** The payload package this repo syncs from. */
@@ -190,9 +179,8 @@ interface NuxtBaseConfig {
190
179
  eslint?: CreateSidebaseEslintOptions;
191
180
  }
192
181
  /**
193
- * Identity helper for a typed `streamctl.config.ts`, the payload analog of the
194
- * CLI's `defineStreamctlConfig`, adding editor inference for this payload's knobs.
195
- * Returns the config unchanged; the CLI validates it at load.
182
+ * Identity helper giving editor inference for this payload's knobs, the analog of the
183
+ * CLI's `defineStreamctlConfig`. Returns the config unchanged; the CLI validates it.
196
184
  */
197
185
  declare function defineNuxtBaseConfig(config: NuxtBaseConfig): NuxtBaseConfig;
198
186
  /** Runtime list of every {@link NuxtBaseCiConfig} key. */
@@ -210,11 +198,9 @@ declare const NUXT_BASE_PNPM_KEYS: string[];
210
198
  /** Runtime list of every {@link NuxtBaseEditorConfig} key. */
211
199
  declare const NUXT_BASE_EDITOR_KEYS: string[];
212
200
  /**
213
- * Every payload KNOB dot-path {@link NuxtBaseConfig} declares (the `ci.*` and
214
- * `automation.*` leaves plus the top-level knobs); excludes the CLI-universal
215
- * fields. The consistency test asserts this set equals the RESOLVED preset chain's
216
- * declared `configKeys` (base + nuxt-app), catching drift between the type and the
217
- * manifest in either direction.
201
+ * Every knob dot-path {@link NuxtBaseConfig} declares, excluding the CLI-universal
202
+ * fields. The consistency test asserts this set equals the resolved preset chain's
203
+ * `configKeys`, catching drift between the type and the manifest in either direction.
218
204
  */
219
205
  declare const NUXT_BASE_CONFIG_KEYS: string[];
220
206
 
package/dist/config.mjs CHANGED
@@ -24,7 +24,9 @@ const NUXT_BASE_DOCKER_KEYS = knobKeys({
24
24
  startCommand: 0
25
25
  });
26
26
  const NUXT_BASE_AUTOMATION_KEYS = knobKeys({
27
- upgradePr: 0
27
+ upgradePr: 0,
28
+ allowWorkflowUpdates: 0,
29
+ prTokenSecret: 0
28
30
  });
29
31
  const NUXT_BASE_SECURITY_KEYS = knobKeys({
30
32
  minimumReleaseAge: 0
@@ -1,5 +1,5 @@
1
- import { C as CreateSidebaseEslintOptions } from '../shared/base-config.CuUhyvQo.mjs';
2
- export { E as ESLINT_OPTION_KEYS } from '../shared/base-config.CuUhyvQo.mjs';
1
+ import { C as CreateSidebaseEslintOptions } from '../shared/base-config.BoberVUk.mjs';
2
+ export { E as ESLINT_OPTION_KEYS } from '../shared/base-config.BoberVUk.mjs';
3
3
  import antfu, { TypedFlatConfigItem } from '@antfu/eslint-config';
4
4
 
5
5
  /** {@link CreateSidebaseEslintOptions} with all defaults applied + the computed type-aware gate. */
@@ -20,10 +20,7 @@ interface ResolvedEslintOptions {
20
20
  testFilePattern: string[];
21
21
  typeAware: boolean;
22
22
  }
23
- /**
24
- * Whether type-aware linting is on: gated behind `LINT_TYPEAWARE=true` so the
25
- * slower type-aware pass stays opt-in (CI/local override).
26
- */
23
+ /** Type-aware linting is gated behind `LINT_TYPEAWARE=true` because it is slow. */
27
24
  declare function isTypeAware(): boolean;
28
25
  /** Apply the documented option defaults and resolve the type-aware gate. */
29
26
  declare function resolveEslintOptions(options?: CreateSidebaseEslintOptions): ResolvedEslintOptions;
@@ -1,5 +1,5 @@
1
- import { C as CreateSidebaseEslintOptions } from '../shared/base-config.CuUhyvQo.js';
2
- export { E as ESLINT_OPTION_KEYS } from '../shared/base-config.CuUhyvQo.js';
1
+ import { C as CreateSidebaseEslintOptions } from '../shared/base-config.BoberVUk.js';
2
+ export { E as ESLINT_OPTION_KEYS } from '../shared/base-config.BoberVUk.js';
3
3
  import antfu, { TypedFlatConfigItem } from '@antfu/eslint-config';
4
4
 
5
5
  /** {@link CreateSidebaseEslintOptions} with all defaults applied + the computed type-aware gate. */
@@ -20,10 +20,7 @@ interface ResolvedEslintOptions {
20
20
  testFilePattern: string[];
21
21
  typeAware: boolean;
22
22
  }
23
- /**
24
- * Whether type-aware linting is on: gated behind `LINT_TYPEAWARE=true` so the
25
- * slower type-aware pass stays opt-in (CI/local override).
26
- */
23
+ /** Type-aware linting is gated behind `LINT_TYPEAWARE=true` because it is slow. */
27
24
  declare function isTypeAware(): boolean;
28
25
  /** Apply the documented option defaults and resolve the type-aware gate. */
29
26
  declare function resolveEslintOptions(options?: CreateSidebaseEslintOptions): ResolvedEslintOptions;
@@ -107,30 +107,27 @@ function buildEslintLayers(options) {
107
107
  imports: "always-multiline"
108
108
  }],
109
109
  "space-infix-ops": ["error"],
110
- // `node/prefer-global/process` is NOT set here: antfu 7.4.3 registers
111
- // eslint-plugin-n (`node`) only inside its own files-scoped object, so setting
112
- // the rule in this plugin-less layer makes ESLint 10 ABORT. It is instead
113
- // neutralized to `"off"` via `.override("antfu/node/rules")` in
114
- // `createSidebaseEslint`, inside antfu's node-scoped object where the plugin
115
- // is registered (see the comment there). The `no-restricted-properties`
116
- // process.env ban below carries the real guard.
110
+ // `node/prefer-global/process` is deliberately not set here: antfu registers
111
+ // eslint-plugin-n only inside its own files-scoped object, so setting the rule in
112
+ // this plugin-less layer makes ESLint 10 abort. It is neutralized via
113
+ // `.override("antfu/node/rules")` in `createSidebaseEslint` instead. The
114
+ // `no-restricted-properties` process.env ban below carries the real guard.
117
115
  "no-unused-expressions": ["error"],
118
116
  "no-param-reassign": ["error"],
119
117
  "no-fallthrough": ["error"],
120
118
  "require-await": ["error"],
121
119
  "ts/no-non-null-assertion": ["error"],
122
- // antfu leaves `ts/no-explicit-any` off; this baseline enforces it, matching the
123
- // shipped `AGENTS.md` ban on `any`. Breaking for consumers (Q5, Option A).
120
+ // antfu leaves `ts/no-explicit-any` off. This baseline enforces it, matching the
121
+ // shipped `AGENTS.md` ban on `any`. Breaking for consumers on adoption.
124
122
  "ts/no-explicit-any": "error",
125
123
  // Type-aware rules antfu enables that this baseline turns off.
126
124
  "ts/no-misused-promises": "off",
127
125
  "ts/no-unsafe-call": "off",
128
126
  "ts/strict-boolean-expressions": "off",
129
127
  "ts/promise-function-async": "off",
130
- // Newer antfu rules outside the established house baseline. `prefer-static-regex`
131
- // is a perf nudge the consuming apps never adopted; `custom-event-name-casing`
132
- // is actively wrong for naive-ui's kebab `update:*` v-model events. Off by
133
- // default; a repo can opt back in via `.append()`.
128
+ // Newer antfu rules outside the house baseline. `prefer-static-regex` is a perf
129
+ // nudge the apps never adopted, and `custom-event-name-casing` is wrong for
130
+ // naive-ui's kebab `update:*` v-model events. Opt back in via `.append()`.
134
131
  "e18e/prefer-static-regex": "off",
135
132
  "vue/custom-event-name-casing": "off"
136
133
  }
@@ -141,17 +138,14 @@ function buildEslintLayers(options) {
141
138
  });
142
139
  configs.push({
143
140
  name: "sidebase/console",
144
- // Source files only: antfu's markdown processor lints fenced code
145
- // blocks as virtual `*.md/*` files, so an un-scoped `no-console` fires inside
146
- // README/doc examples. This carve-out leaves real `.ts`/`.vue`/... enforcement intact.
141
+ // Source files only. antfu's markdown processor lints fenced code blocks as virtual
142
+ // `*.md/*` files, so an un-scoped `no-console` fires inside doc examples.
147
143
  ignores: ["**/*.md/**"],
148
144
  rules: {
149
- // Always pass an explicit options object: a severity-only override would
150
- // retain antfu's `{ allow: ["warn", "error"] }`. `"error"` (hard-ban)
151
- // emits `{}` (no-console's schema rejects an empty `allow` array), which
152
- // replaces those options so every `console.*` is banned. An empty
153
- // allow-list was normalized to `"error"` in resolveEslintOptions, so the
154
- // array branch here is always a non-empty allow-list (no cast needed).
145
+ // Always pass an explicit options object, or a severity-only override retains
146
+ // antfu's `{ allow: ["warn", "error"] }`. A hard ban emits `{}`, since no-console
147
+ // rejects an empty `allow` array. `resolveEslintOptions` already normalized an
148
+ // empty allow-list to `"error"`, so the array branch is always non-empty.
155
149
  "no-console": options.console === "error" ? ["error", {}] : ["error", { allow: options.console }]
156
150
  }
157
151
  });
@@ -229,48 +223,23 @@ function createSidebaseEslint(options = {}) {
229
223
  return antfu(
230
224
  {
231
225
  type: "app",
232
- // `local.*` files and directories are personal, git-ignored scratch space
233
- // and are never linted.
234
- ignores: ["**/local.*", "**/local.*/**"],
235
- // Org house style: 2-space indent, single quotes, Vue on,
236
- // JSON/YAML linting off (handled elsewhere).
226
+ // Personal scratch space. Root-anchored so `src/path/local.ts` stays linted.
227
+ ignores: ["local.*", "local.*/**", "prisma/local.*", "prisma/local.*/**"],
228
+ // House style. JSON and YAML linting are handled elsewhere.
237
229
  stylistic: { indent: 2, quotes: "single" },
238
230
  vue: true,
239
231
  jsonc: false,
240
232
  yaml: false,
241
- // Type-aware is gated behind `LINT_TYPEAWARE`; when on, point at the repo
242
- // tsconfig and exclude the configured paths from the type-aware program.
233
+ // Gated behind `LINT_TYPEAWARE`. When on, point at the repo tsconfig and
234
+ // exclude the configured paths from the type-aware program.
243
235
  typescript: resolved.typeAware ? { tsconfigPath: "tsconfig.json", ignoresTypeAware: resolved.ignoresTypeAware } : true
244
236
  },
245
237
  ...buildEslintLayers(resolved)
246
238
  ).override("antfu/node/rules", {
247
- // antfu 7.4.3's node layer defaults `node/prefer-global/process` to
248
- // `["error", "never"]` (demands `require("process")`), which flags EVERY legit
249
- // global `process` use in an ESM Nuxt app (env modules, server plugins, loggers).
250
- // Leaving the rule unset is not enough: antfu's `never` then wins in consumer
251
- // resolution. Neutralize it HERE, inside antfu's own node-scoped config where the
252
- // `node` plugin IS registered; setting it in a plugin-less object makes ESLint 10
253
- // abort. `"off"`, not `["error", "always"]`, because `"always"` would wrongly flag
254
- // the generated Prisma client's `import * as process from 'node:process'`.
255
- //
256
- // Note what this does NOT mean. prefer-global is not merely redundant here:
257
- // `["error", "always"]` would also close a real hole, because
258
- // `no-restricted-properties` keys on the `process.env` MEMBER EXPRESSION, and any
259
- // import that renames the binding erases the shape it matches. Measured against
260
- // this factory, the property ban alone catches `process.env.X`,
261
- // `const { env } = process`, and a default import still named `process`, but NOT
262
- // `import { env }`, `import { env as e }`, `import * as proc`, or
263
- // `import proc from "node:process"`. Those are closed at the import site instead,
264
- // by the `node:process` / `process` entries in `paths` (see `importRestrictions` in
265
- // rules.ts): narrower than flipping prefer-global, and free of the Prisma-client
266
- // false positive.
267
- //
268
- // With `importNames: ["env", "default"]` that is now the COMPLETE set, not a sample.
269
- // Every way to reach `process.env` is covered by one rule or the other: the member
270
- // expression and an un-renamed default import at the USAGE site, and the named,
271
- // renamed-named, namespace and renamed-default imports at the IMPORT site. The
272
- // un-renamed default being caught at the usage site rather than by the import ban is
273
- // the asymmetry that hid the renamed-default hole for two rounds of review.
239
+ // antfu's `"never"` default flags every legitimate global `process` use. Neutralize
240
+ // it here, inside antfu's node-scoped config: a plugin-less object aborts ESLint 10.
241
+ // `"off"` and not `"always"`, which would flag the generated Prisma client. The
242
+ // `process.env` hole is covered at the import site by `importRestrictions`.
274
243
  rules: { "node/prefer-global/process": "off" }
275
244
  });
276
245
  }
@@ -6,27 +6,12 @@ interface SchemaEngineDatasource {
6
6
  shadowDatabaseUrl?: string;
7
7
  }
8
8
  /**
9
- * Seed the three Prisma connection env vars with localhost dev defaults when UNSET.
10
- * This is a deliberate SIDE EFFECT on `env` (defaults to `process.env`). Necessary because
11
- * once a `prisma.config.ts` exists Prisma stops auto-loading `.env`, so a schema that
12
- * reads `env("DATABASE_URL")` / `env("DIRECT_DATABASE_URL")` would fail at rest.
9
+ * Seed the Prisma connection env vars with localhost dev defaults when unset.
10
+ * Deliberately mutates `env`: once a `prisma.config.ts` exists Prisma stops auto-loading
11
+ * `.env`, so a schema reading `env("DATABASE_URL")` would fail at rest.
13
12
  *
14
- * Call it (after `import "dotenv/config"`) in the config file so the Prisma CLI runs
15
- * with ZERO env; a real `.env`/shell value always wins. `buildPrismaConfig` then reads
16
- * the seeded env and derives its direct-connection + shadow datasource.
17
- *
18
- * TWO paths, not one:
19
- * - **Bare, or an explicit `DIRECT_DATABASE_URL`.** Seeds all three. Defaults:
20
- * direct = local postgres, pooled = direct + `pgbouncer=1`, shadow = direct with a
21
- * `/prisma-shadow` database.
22
- * - **A real `DATABASE_URL` and no direct URL.** Seeds ONLY `DIRECT_DATABASE_URL`,
23
- * derived from the pooled URL, and returns early. No shadow is seeded on purpose:
24
- * deriving one would name a `/prisma-shadow` database on the production host, which
25
- * Prisma CREATEs and DROPs.
26
- *
27
- * An empty-string value counts as unset throughout; `docker-compose` produces `""` for an
28
- * undefined variable, and treating it as present is how the localhost default used to
29
- * reach production.
13
+ * Call it after `import "dotenv/config"`. A real value always wins, and an empty string
14
+ * counts as unset.
30
15
  */
31
16
  declare function applyPrismaDevEnv(env?: Record<string, string | undefined>): void;
32
17
  /**
@@ -35,13 +20,12 @@ declare function applyPrismaDevEnv(env?: Record<string, string | undefined>): vo
35
20
  */
36
21
  declare function stripPgbouncerParams(url: string): string;
37
22
  /**
38
- * Resolve the schema engine's datasource (Pattern B):
39
- * - direct URL = `DIRECT_DATABASE_URL`, else `DATABASE_URL` with pgbouncer params stripped;
40
- * - shadow DB = `SHADOW_DATABASE_URL` when present.
23
+ * Resolve the schema engine's datasource:
24
+ * - direct URL = `DIRECT_DATABASE_URL`, else `DATABASE_URL` with pooler params stripped
25
+ * - shadow DB = `SHADOW_DATABASE_URL` when present
41
26
  *
42
- * Returns `undefined` when neither a direct nor a pooled URL is set, so the
43
- * config falls back to the schema's own `datasource` block (e.g. during
44
- * `prisma generate` without a database).
27
+ * Returns `undefined` when neither is set, so the config falls back to the schema's own
28
+ * `datasource` block, e.g. during `prisma generate` without a database.
45
29
  */
46
30
  declare function resolveSchemaEngineDatasource(env: Record<string, string | undefined>): SchemaEngineDatasource | undefined;
47
31
 
@@ -54,8 +38,8 @@ interface BuildPrismaConfigOptions {
54
38
  typedSql?: boolean;
55
39
  }
56
40
  /**
57
- * Build the shared `@sidebase` Prisma config (Prisma 6.19 "Pattern B").
58
- * Wrap the result in `defineConfig`:
41
+ * Build the shared `@sidebase` Prisma config. Gives the schema engine a pooler-free
42
+ * direct connection. Prisma 7's config shape is not covered.
59
43
  *
60
44
  * ```ts
61
45
  * // prisma.config.ts
@@ -63,10 +47,6 @@ interface BuildPrismaConfigOptions {
63
47
  * import { buildPrismaConfig } from "@sidebase/base-config/prisma";
64
48
  * export default defineConfig(buildPrismaConfig({ views: true, typedSql: true }));
65
49
  * ```
66
- *
67
- * Reads `DATABASE_URL` / `DIRECT_DATABASE_URL` / `SHADOW_DATABASE_URL` (the
68
- * schema engine gets a pgbouncer-free direct connection). Prisma 7's changed
69
- * config shape is out of scope for v1.
70
50
  */
71
51
  declare function buildPrismaConfig(options?: BuildPrismaConfigOptions, env?: Record<string, string | undefined>): PrismaConfig;
72
52
 
@@ -6,27 +6,12 @@ interface SchemaEngineDatasource {
6
6
  shadowDatabaseUrl?: string;
7
7
  }
8
8
  /**
9
- * Seed the three Prisma connection env vars with localhost dev defaults when UNSET.
10
- * This is a deliberate SIDE EFFECT on `env` (defaults to `process.env`). Necessary because
11
- * once a `prisma.config.ts` exists Prisma stops auto-loading `.env`, so a schema that
12
- * reads `env("DATABASE_URL")` / `env("DIRECT_DATABASE_URL")` would fail at rest.
9
+ * Seed the Prisma connection env vars with localhost dev defaults when unset.
10
+ * Deliberately mutates `env`: once a `prisma.config.ts` exists Prisma stops auto-loading
11
+ * `.env`, so a schema reading `env("DATABASE_URL")` would fail at rest.
13
12
  *
14
- * Call it (after `import "dotenv/config"`) in the config file so the Prisma CLI runs
15
- * with ZERO env; a real `.env`/shell value always wins. `buildPrismaConfig` then reads
16
- * the seeded env and derives its direct-connection + shadow datasource.
17
- *
18
- * TWO paths, not one:
19
- * - **Bare, or an explicit `DIRECT_DATABASE_URL`.** Seeds all three. Defaults:
20
- * direct = local postgres, pooled = direct + `pgbouncer=1`, shadow = direct with a
21
- * `/prisma-shadow` database.
22
- * - **A real `DATABASE_URL` and no direct URL.** Seeds ONLY `DIRECT_DATABASE_URL`,
23
- * derived from the pooled URL, and returns early. No shadow is seeded on purpose:
24
- * deriving one would name a `/prisma-shadow` database on the production host, which
25
- * Prisma CREATEs and DROPs.
26
- *
27
- * An empty-string value counts as unset throughout; `docker-compose` produces `""` for an
28
- * undefined variable, and treating it as present is how the localhost default used to
29
- * reach production.
13
+ * Call it after `import "dotenv/config"`. A real value always wins, and an empty string
14
+ * counts as unset.
30
15
  */
31
16
  declare function applyPrismaDevEnv(env?: Record<string, string | undefined>): void;
32
17
  /**
@@ -35,13 +20,12 @@ declare function applyPrismaDevEnv(env?: Record<string, string | undefined>): vo
35
20
  */
36
21
  declare function stripPgbouncerParams(url: string): string;
37
22
  /**
38
- * Resolve the schema engine's datasource (Pattern B):
39
- * - direct URL = `DIRECT_DATABASE_URL`, else `DATABASE_URL` with pgbouncer params stripped;
40
- * - shadow DB = `SHADOW_DATABASE_URL` when present.
23
+ * Resolve the schema engine's datasource:
24
+ * - direct URL = `DIRECT_DATABASE_URL`, else `DATABASE_URL` with pooler params stripped
25
+ * - shadow DB = `SHADOW_DATABASE_URL` when present
41
26
  *
42
- * Returns `undefined` when neither a direct nor a pooled URL is set, so the
43
- * config falls back to the schema's own `datasource` block (e.g. during
44
- * `prisma generate` without a database).
27
+ * Returns `undefined` when neither is set, so the config falls back to the schema's own
28
+ * `datasource` block, e.g. during `prisma generate` without a database.
45
29
  */
46
30
  declare function resolveSchemaEngineDatasource(env: Record<string, string | undefined>): SchemaEngineDatasource | undefined;
47
31
 
@@ -54,8 +38,8 @@ interface BuildPrismaConfigOptions {
54
38
  typedSql?: boolean;
55
39
  }
56
40
  /**
57
- * Build the shared `@sidebase` Prisma config (Prisma 6.19 "Pattern B").
58
- * Wrap the result in `defineConfig`:
41
+ * Build the shared `@sidebase` Prisma config. Gives the schema engine a pooler-free
42
+ * direct connection. Prisma 7's config shape is not covered.
59
43
  *
60
44
  * ```ts
61
45
  * // prisma.config.ts
@@ -63,10 +47,6 @@ interface BuildPrismaConfigOptions {
63
47
  * import { buildPrismaConfig } from "@sidebase/base-config/prisma";
64
48
  * export default defineConfig(buildPrismaConfig({ views: true, typedSql: true }));
65
49
  * ```
66
- *
67
- * Reads `DATABASE_URL` / `DIRECT_DATABASE_URL` / `SHADOW_DATABASE_URL` (the
68
- * schema engine gets a pgbouncer-free direct connection). Prisma 7's changed
69
- * config shape is out of scope for v1.
70
50
  */
71
51
  declare function buildPrismaConfig(options?: BuildPrismaConfigOptions, env?: Record<string, string | undefined>): PrismaConfig;
72
52
 
@@ -1,7 +1,4 @@
1
- /**
2
- * Options for the published ESLint factory (`@sidebase/base-config/eslint`).
3
- * Covers the per-repo variance found across the consuming repos.
4
- */
1
+ /** Options for the published ESLint factory (`@sidebase/base-config/eslint`). */
5
2
  interface CreateSidebaseEslintOptions {
6
3
  /** Zod `.extend()/.merge()/.passthrough()` bans and/or `import * as z` enforcement. Default `"none"` (opt-in). */
7
4
  zod?: "full" | "import-style" | "none";
@@ -36,10 +33,9 @@ interface CreateSidebaseEslintOptions {
36
33
  testFilePattern?: string[];
37
34
  }
38
35
  /**
39
- * Runtime list of every {@link CreateSidebaseEslintOptions} key, for config
40
- * validation/iteration. The `satisfies Record<keyof ..., 0>` map makes this
41
- * exhaustive: adding a future option to the interface fails to compile until
42
- * the key is listed here too, so the validator allow-list can never drift.
36
+ * Runtime list of every {@link CreateSidebaseEslintOptions} key. The `satisfies` map
37
+ * keeps it exhaustive: a new option fails to compile until it is listed here, so the
38
+ * validator allow-list cannot drift.
43
39
  */
44
40
  declare const ESLINT_OPTION_KEYS: string[];
45
41
 
@@ -1,7 +1,4 @@
1
- /**
2
- * Options for the published ESLint factory (`@sidebase/base-config/eslint`).
3
- * Covers the per-repo variance found across the consuming repos.
4
- */
1
+ /** Options for the published ESLint factory (`@sidebase/base-config/eslint`). */
5
2
  interface CreateSidebaseEslintOptions {
6
3
  /** Zod `.extend()/.merge()/.passthrough()` bans and/or `import * as z` enforcement. Default `"none"` (opt-in). */
7
4
  zod?: "full" | "import-style" | "none";
@@ -36,10 +33,9 @@ interface CreateSidebaseEslintOptions {
36
33
  testFilePattern?: string[];
37
34
  }
38
35
  /**
39
- * Runtime list of every {@link CreateSidebaseEslintOptions} key, for config
40
- * validation/iteration. The `satisfies Record<keyof ..., 0>` map makes this
41
- * exhaustive: adding a future option to the interface fails to compile until
42
- * the key is listed here too, so the validator allow-list can never drift.
36
+ * Runtime list of every {@link CreateSidebaseEslintOptions} key. The `satisfies` map
37
+ * keeps it exhaustive: a new option fails to compile until it is listed here, so the
38
+ * validator allow-list cannot drift.
43
39
  */
44
40
  declare const ESLINT_OPTION_KEYS: string[];
45
41