@sidebase/base-config 0.2.0 → 0.2.1
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 +28 -24
- package/dist/config.d.mts +49 -67
- package/dist/config.d.ts +49 -67
- package/dist/eslint/index.d.mts +3 -6
- package/dist/eslint/index.d.ts +3 -6
- package/dist/eslint/index.mjs +25 -56
- package/dist/prisma/index.d.mts +12 -32
- package/dist/prisma/index.d.ts +12 -32
- package/dist/shared/{base-config.CuUhyvQo.d.mts → base-config.BoberVUk.d.mts} +4 -8
- package/dist/shared/{base-config.CuUhyvQo.d.ts → base-config.BoberVUk.d.ts} +4 -8
- package/docs/migration.md +12 -13
- package/package.json +1 -1
- package/presets/base/AGENTS.md +9 -0
- package/presets/base/dockerignore +7 -8
- package/presets/base/github/workflows/streamctl-upgrade.yml +13 -23
- package/presets/base/gitignore +6 -5
- package/presets/base/oxlintrc.json +3 -2
- package/presets/base/pnpm-workspace.yaml +9 -16
- package/presets/config.template.ts +2 -2
- package/presets/nuxt-app/Dockerfile +15 -20
- package/presets/nuxt-app/github/workflows/ci.yml +5 -6
- package/presets/nuxt-app/github/workflows/pr-preview-cleanup.yml +2 -2
- package/presets/nuxt-app/preset.json +1 -1
- package/presets/nuxt-app/templates/ci/e2e-job.yml +2 -5
package/dist/eslint/index.mjs
CHANGED
|
@@ -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
|
|
111
|
-
// eslint-plugin-n
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
// `
|
|
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
|
|
123
|
-
// shipped `AGENTS.md` ban on `any`. Breaking for consumers
|
|
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
|
|
131
|
-
//
|
|
132
|
-
//
|
|
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
|
|
145
|
-
//
|
|
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
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
//
|
|
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
|
-
//
|
|
233
|
-
|
|
234
|
-
|
|
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
|
-
//
|
|
242
|
-
//
|
|
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
|
|
248
|
-
//
|
|
249
|
-
//
|
|
250
|
-
//
|
|
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
|
}
|
package/dist/prisma/index.d.mts
CHANGED
|
@@ -6,27 +6,12 @@ interface SchemaEngineDatasource {
|
|
|
6
6
|
shadowDatabaseUrl?: string;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Seed the
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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
|
|
15
|
-
*
|
|
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
|
|
39
|
-
* - direct URL = `DIRECT_DATABASE_URL`, else `DATABASE_URL` with
|
|
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
|
|
43
|
-
*
|
|
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
|
|
58
|
-
*
|
|
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
|
|
package/dist/prisma/index.d.ts
CHANGED
|
@@ -6,27 +6,12 @@ interface SchemaEngineDatasource {
|
|
|
6
6
|
shadowDatabaseUrl?: string;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Seed the
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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
|
|
15
|
-
*
|
|
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
|
|
39
|
-
* - direct URL = `DIRECT_DATABASE_URL`, else `DATABASE_URL` with
|
|
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
|
|
43
|
-
*
|
|
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
|
|
58
|
-
*
|
|
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
|
|
40
|
-
*
|
|
41
|
-
*
|
|
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
|
|
40
|
-
*
|
|
41
|
-
*
|
|
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
|
|
package/docs/migration.md
CHANGED
|
@@ -334,10 +334,10 @@ the managed file and is reverted on the next sync.
|
|
|
334
334
|
warns you. `streamctl check` stays green, the file looks deliberate, and a package whose
|
|
335
335
|
install scripts are blocked still installs.
|
|
336
336
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
337
|
+
The consequence is narrower than it first appears. The usual suspects (`sharp`,
|
|
338
|
+
`@tailwindcss/oxide`, `unrs-resolver`, `@parcel/watcher`) ship their native binary as a
|
|
339
|
+
prebuilt optional dependency, so on a platform with a prebuild they keep working whether or
|
|
340
|
+
not they are approved, cold install included. Verified across pnpm
|
|
341
341
|
10.28.1, 10.29.1 and 10.29.3. Where the loss is real:
|
|
342
342
|
|
|
343
343
|
- architectures with no prebuild, where the binary genuinely has to be compiled
|
|
@@ -546,13 +546,12 @@ too, so on first sync the payload appends its block to whatever your repository
|
|
|
546
546
|
Your existing lines stay above it. Nothing is overwritten and nothing is reported.
|
|
547
547
|
|
|
548
548
|
Most of the leftovers are harmless. Ignore patterns are additive, so a duplicated `node_modules`
|
|
549
|
-
or `.env` above the block is
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
time.
|
|
549
|
+
or `.env` above the block is inert; it changes nothing about what the build context carries.
|
|
550
|
+
Delete them anyway, and not for tidiness. The detector below is the only thing that will ever
|
|
551
|
+
tell you a payload entry has started shadowing something of yours, and it is not a one-shot
|
|
552
|
+
check. A future payload version can add an entry that collides with a line you kept above the
|
|
553
|
+
block. A file with leftover duplicates reads `AFFECTED` forever, so it can no longer distinguish
|
|
554
|
+
that from the noise. Clearing them keeps the check able to answer next time.
|
|
556
555
|
|
|
557
556
|
**The case that bites is a negation.** `.dockerignore` is last-match-wins, and the managed block
|
|
558
557
|
is appended at the BOTTOM, so every payload entry beats anything you wrote above it. A repository
|
|
@@ -822,5 +821,5 @@ keeps its own command this way.
|
|
|
822
821
|
|
|
823
822
|
Nothing here is destructive if you work on a branch. `sync` rewrites tracked files, so
|
|
824
823
|
`git diff` shows everything it did and `git restore` undoes it. Keep the migration on its
|
|
825
|
-
own branch and its own commit so that if the sync diff turns out to be larger than
|
|
826
|
-
expected, reverting it is one operation
|
|
824
|
+
own branch and its own commit, so that if the sync diff turns out to be larger than
|
|
825
|
+
expected, reverting it is one operation.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sidebase/base-config",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Shared @sidebase base configuration for Nuxt repos: ESLint / Prisma / tsconfig factories on npm, plus the streamctl file-sync preset payload",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sidebase",
|
package/presets/base/AGENTS.md
CHANGED
|
@@ -10,6 +10,15 @@ follow. They are the same across every repo in the fleet.
|
|
|
10
10
|
- Never commit secrets, credentials, or generated build artifacts.
|
|
11
11
|
- Keep all code, comments and identifiers in English.
|
|
12
12
|
|
|
13
|
+
## Comments & wording
|
|
14
|
+
|
|
15
|
+
- Keep comments short. Say WHY the code is the way it is, not what it plainly does.
|
|
16
|
+
- ASCII only: no em dash, en dash, arrow, ellipsis, curly quote, or emoji.
|
|
17
|
+
- One idea per sentence. Cut filler openers ("It is worth noting") and inflated words
|
|
18
|
+
("leverage", "utilize", "robust", "seamless").
|
|
19
|
+
- Do not leave a comment describing an alternative you rejected, or internal ticket
|
|
20
|
+
shorthand a reader cannot resolve.
|
|
21
|
+
|
|
13
22
|
## Types & correctness
|
|
14
23
|
|
|
15
24
|
- Use precise types; avoid `any` and unchecked casts. Parse and validate external input at the boundary instead of trusting it downstream.
|
|
@@ -12,16 +12,15 @@ tests
|
|
|
12
12
|
.env
|
|
13
13
|
.env.*
|
|
14
14
|
!.env.example
|
|
15
|
-
# The build
|
|
16
|
-
#
|
|
17
|
-
# is intentionally allowed through.
|
|
15
|
+
# The build stage globs `.npmrc*`, so keep token-bearing backups like
|
|
16
|
+
# `.npmrc.local` out of the build context. `.npmrc` itself is allowed through.
|
|
18
17
|
.npmrc.*
|
|
19
18
|
.DS_Store
|
|
20
|
-
# Local dev state
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
# .gitignore), so `**/local.*` is required to reach the nested paths.
|
|
19
|
+
# Local dev state from `pnpm db` or `docker compose up`. `prisma/pglite-data` is
|
|
20
|
+
# tens of MB, and root-owned `prisma/local.postgres_data` fails a rootless build.
|
|
21
|
+
# Root-anchored so `src/path/local.ts` still reaches the build context.
|
|
24
22
|
prisma/client
|
|
25
23
|
prisma/pglite-data
|
|
26
24
|
pgliteHealthz
|
|
27
|
-
|
|
25
|
+
local.*
|
|
26
|
+
prisma/local.*
|
|
@@ -1,18 +1,11 @@
|
|
|
1
|
-
# Managed by streamctl
|
|
2
|
-
#
|
|
3
|
-
# streamctl.config.ts. See the payload README "Upgrade-PR workflow" for enabling.
|
|
1
|
+
# Managed by streamctl. Off by default; lands only when a repo sets
|
|
2
|
+
# `automation: { upgradePr: true }`. See the README section "Upgrade-PR workflow".
|
|
4
3
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# A PR created with `GITHUB_TOKEN` does NOT trigger `pull_request` workflows, so
|
|
8
|
-
# this repo's own `check` gate would never run on the bot's PR. The bot identity
|
|
9
|
-
# for the fleet is still being decided; treat this file as inert and provide the
|
|
10
|
-
# secret before enabling. No registry token is needed: the payload is public npm.
|
|
11
|
-
# A repo with OTHER private dependencies must opt this file out
|
|
12
|
-
# (`files: { ".github/workflows/streamctl-upgrade.yml": "off" }`) and wire its own auth.
|
|
4
|
+
# Needs `secrets.STREAMCTL_PR_TOKEN`: a PR opened with `GITHUB_TOKEN` does not trigger
|
|
5
|
+
# `pull_request` workflows, so the repo's own `check` gate would never run on it.
|
|
13
6
|
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
7
|
+
# A repo with private dependencies must opt this file out and wire its own auth:
|
|
8
|
+
# `files: { ".github/workflows/streamctl-upgrade.yml": "off" }`.
|
|
16
9
|
name: streamctl upgrade
|
|
17
10
|
|
|
18
11
|
on:
|
|
@@ -20,8 +13,8 @@ on:
|
|
|
20
13
|
- cron: "0 6 * * 1" # Mondays 06:00 UTC
|
|
21
14
|
workflow_dispatch:
|
|
22
15
|
|
|
23
|
-
#
|
|
24
|
-
#
|
|
16
|
+
# Every PR and issue write below uses STREAMCTL_PR_TOKEN, so the default token
|
|
17
|
+
# only needs to read the repo for checkout.
|
|
25
18
|
permissions:
|
|
26
19
|
contents: read
|
|
27
20
|
|
|
@@ -32,9 +25,8 @@ jobs:
|
|
|
32
25
|
upgrade:
|
|
33
26
|
runs-on: ubuntu-latest
|
|
34
27
|
steps:
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
# then use `${{ steps.bot.outputs.token }}` in place of STREAMCTL_PR_TOKEN below:
|
|
28
|
+
# To mint an App token in-workflow instead of storing a PAT, uncomment this
|
|
29
|
+
# and use `${{ steps.bot.outputs.token }}` in place of STREAMCTL_PR_TOKEN:
|
|
38
30
|
#
|
|
39
31
|
# - id: bot
|
|
40
32
|
# uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0
|
|
@@ -59,8 +51,7 @@ jobs:
|
|
|
59
51
|
- name: Install dependencies
|
|
60
52
|
run: pnpm install --frozen-lockfile
|
|
61
53
|
|
|
62
|
-
# Exit codes
|
|
63
|
-
# date (stop, no PR); 3 = the repo already has drift (open an issue, not a PR).
|
|
54
|
+
# Exit codes: 4 = update available, 0 = up to date, 3 = repo already drifted.
|
|
64
55
|
- id: check
|
|
65
56
|
name: Check for a payload update
|
|
66
57
|
run: |
|
|
@@ -91,9 +82,8 @@ jobs:
|
|
|
91
82
|
set -e
|
|
92
83
|
cat streamctl-upgrade.json
|
|
93
84
|
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
# reconciles with `streamctl sync --interactive`.
|
|
85
|
+
# Exit 2 means the sync hit conflicts and rolled back. Bump only the pin and
|
|
86
|
+
# devDependency so the PR carries a diff a human reconciles interactively.
|
|
97
87
|
- name: Prepare a plan-only bump (interactive sync required)
|
|
98
88
|
if: ${{ steps.upgrade.outputs.code == '2' }}
|
|
99
89
|
run: pnpm streamctl upgrade --no-install --json > streamctl-upgrade.json
|
package/presets/base/gitignore
CHANGED
|
@@ -11,9 +11,10 @@ pglite-debug.log
|
|
|
11
11
|
prisma/*.db
|
|
12
12
|
prisma/migrations/dev
|
|
13
13
|
.DS_Store
|
|
14
|
-
# streamctl
|
|
15
|
-
local.*
|
|
16
|
-
local.*/
|
|
17
|
-
|
|
18
|
-
#
|
|
14
|
+
# streamctl scratch. Root-anchored so `src/path/local.ts` stays tracked.
|
|
15
|
+
/local.*
|
|
16
|
+
/local.*/
|
|
17
|
+
prisma/local.*
|
|
18
|
+
# CLAUDE.md is managed by streamctl. A user-global gitignore matching the name
|
|
19
|
+
# everywhere would silently untrack it, so force-allow it.
|
|
19
20
|
!CLAUDE.md
|
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
# Managed by streamctl
|
|
1
|
+
# Managed by streamctl. pnpm's own settings file.
|
|
2
2
|
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
# it gates fresh resolution only, so `--frozen-lockfile` installs are unaffected.
|
|
7
|
-
# `@sidebase/*` is exempt: the first-party scope (this payload + the streamctl CLI),
|
|
8
|
-
# published by the org itself, so a payload release reaches the fleet the same day.
|
|
3
|
+
# Cooldown: a version must be ${MIN_RELEASE_AGE} minutes old before pnpm resolves it,
|
|
4
|
+
# giving a compromised release time to be yanked. Needs pnpm >= 10.16. Gates fresh
|
|
5
|
+
# resolution only, so `--frozen-lockfile` is unaffected. `@sidebase/*` is exempt.
|
|
9
6
|
#
|
|
10
|
-
# `packages: []` is
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# A real monorepo owns this key itself, so opt the file out with
|
|
14
|
-
# `files: { "pnpm-workspace.yaml": "off" }` in .streamctl/config.ts.
|
|
7
|
+
# `packages: []` is required: pnpm otherwise defaults it to `**`, promoting every nested
|
|
8
|
+
# package.json to a workspace project and breaking `--frozen-lockfile`. A monorepo should
|
|
9
|
+
# opt out with `files: { "pnpm-workspace.yaml": "off" }`.
|
|
15
10
|
#
|
|
16
|
-
# `onlyBuiltDependencies`
|
|
17
|
-
#
|
|
18
|
-
# needs; add extras via `pnpm: { onlyBuiltDependencies: [...] }` rather than running
|
|
19
|
-
# `pnpm approve-builds` (which writes here and would be reverted on the next sync).
|
|
11
|
+
# `onlyBuiltDependencies` allowlists postinstall scripts. Add extras through the `pnpm`
|
|
12
|
+
# knob, not `pnpm approve-builds`, which writes here and is reverted on the next sync.
|
|
20
13
|
packages: []
|
|
21
14
|
minimumReleaseAge: ${MIN_RELEASE_AGE}
|
|
22
15
|
minimumReleaseAgeExclude:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineNuxtBaseConfig } from '@sidebase/base-config'
|
|
2
2
|
|
|
3
|
-
// Scaffolded by `streamctl init`. `defineNuxtBaseConfig`
|
|
4
|
-
//
|
|
3
|
+
// Scaffolded by `streamctl init`. `defineNuxtBaseConfig` types the knobs below.
|
|
4
|
+
// The CLI validates this file on every sync.
|
|
5
5
|
export default defineNuxtBaseConfig({
|
|
6
6
|
package: '__PACKAGE__',
|
|
7
7
|
base: '__BASE__',
|