@at-flux/astro-feature-flags 1.0.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/LICENSE +21 -0
- package/README.md +297 -0
- package/dist/dev-toolbar-app.d.mts +16 -0
- package/dist/dev-toolbar-app.d.mts.map +1 -0
- package/dist/dev-toolbar-app.mjs +407 -0
- package/dist/dev-toolbar-app.mjs.map +1 -0
- package/dist/dev-toolbar-flag-icon-BHCQJ53N.mjs +10 -0
- package/dist/dev-toolbar-flag-icon-BHCQJ53N.mjs.map +1 -0
- package/dist/index.d.mts +103 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +1107 -0
- package/dist/index.mjs.map +1 -0
- package/dist/runtime.d.mts +115 -0
- package/dist/runtime.d.mts.map +1 -0
- package/dist/runtime.mjs +280 -0
- package/dist/runtime.mjs.map +1 -0
- package/docs/assets/element-gating.png +0 -0
- package/docs/assets/page-gating.png +0 -0
- package/docs/assets/toolbar-feature-flags.png +0 -0
- package/docs/how-to/hide-from-sitemaps.md +49 -0
- package/docs/testing.md +40 -0
- package/example/README.md +18 -0
- package/example/astro.config.mjs +26 -0
- package/example/ff.json +26 -0
- package/example/package.json +22 -0
- package/example/pnpm-lock.yaml +4022 -0
- package/example/src/env.d.ts +2 -0
- package/example/src/layouts/Layout.astro +21 -0
- package/example/src/pages/hot/index.astro +23 -0
- package/example/src/pages/hot-dev/index.astro +18 -0
- package/example/src/pages/hot-dev/sub/index.astro +21 -0
- package/example/src/pages/hot-feature-1/index.astro +38 -0
- package/example/src/pages/index.astro +102 -0
- package/example/src/styles/global.css +22 -0
- package/example/tsconfig.json +4 -0
- package/package.json +68 -0
- package/src/badge-layout.ts +146 -0
- package/src/dev-head-inject.ts +26 -0
- package/src/dev-inline-runtimes.ts +397 -0
- package/src/dev-outline-css.ts +449 -0
- package/src/dev-toolbar-app.ts +516 -0
- package/src/dev-toolbar-flag-icon.ts +9 -0
- package/src/index.ts +417 -0
- package/src/inline-script.ts +14 -0
- package/src/production-html-cull.ts +133 -0
- package/src/route-prefix-js.ts +7 -0
- package/src/runtime.ts +575 -0
- package/virtual-astro-feature-flags.d.ts +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 atflux
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# @at-flux/astro-feature-flags
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@at-flux/astro-feature-flags)
|
|
4
|
+
[](https://github.com/at-flux/astroflare/actions/workflows/ci.yml)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img src="./docs/assets/toolbar-feature-flags.png" alt="Feature Flags Toolbar" width="50%" style="max-width:500px;" />
|
|
9
|
+
<img src="./docs/assets/element-gating.png" alt="Feature Flags element gating" width="40%" style="max-width:400px;" />
|
|
10
|
+
<br/>
|
|
11
|
+
<img src="./docs/assets/page-gating.png" alt="Feature Flags route gating" width="60%" style="max-width:600px;" />
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
Feature flags for Astro with a declarative config:
|
|
15
|
+
|
|
16
|
+
- per-flag declaration (`colour`/`color` for the dev toolbar, optional `routes` for matching pages)
|
|
17
|
+
- **Two environments:** **Astro dev** (`astro dev`) vs **non-dev builds** (production deploys, `astro build` in CI, staging, …). Locally, the integration uses a built-in **dev** environment layer (injected for you; all flags on at resolve time). For shipped output you declare layers such as **`prod`** / **`staging`** with `when` + `flags`. Exactly one `when: true` for the selected environment unless you override with **`forceEnvironment`** / **`AFF_ENVIRONMENT`**.
|
|
18
|
+
- **Route gating (non-dev):** If a pathname matches a flag’s `routes` and that flag is **off** for the active layer, **static** `dist/` output under that prefix is **removed after build** (and you should filter those URLs from sitemaps—see how-to). Server/hybrid apps still need their own runtime routing if URLs can be requested without a matching static file. If the flag is **on**, routes emit like any other page.
|
|
19
|
+
- **Route overlap:** `shouldIncludePath`, `shouldIncludeRoute`, and `shouldIncludePathForEnvironment` use the **first** matching `routes` entry from `Object.entries` order, not longest-prefix. `matchedFeatureRoutePrefix` / `routeFeatureTokensForPath` use **longest** match — avoid overlapping patterns unless order is intentional.
|
|
20
|
+
- element gating via namespaced attributes (`data-ff` or `data-ff-<token>` by default)
|
|
21
|
+
- production static HTML: gated `data-ff` nodes culled, dev-only CSS not shipped (`featureFlagStyles` is empty); dev route attributes (`data-ff-route*`) are stripped from `<html>`
|
|
22
|
+
- route badge + production route pruning
|
|
23
|
+
- dev toolbar for enabled/outline/badge/colour preview (when a URL would be pruned for a configured layer, the overlay names **environment keys**, not `NODE_ENV` text)
|
|
24
|
+
|
|
25
|
+
## Terminology (short)
|
|
26
|
+
|
|
27
|
+
| Term | Meaning |
|
|
28
|
+
| ---- | ------- |
|
|
29
|
+
| **Astro dev** | Local `astro dev` — the built-in dev layer is active; all flags on at resolve time; dev toolbar only affects the browser. |
|
|
30
|
+
| **Non-dev build** | `astro build` / preview / deploy with a shipped layer (`prod`, `staging`, …): `environments.<key>.flags` drives SSR, HTML culling, and route pruning. |
|
|
31
|
+
| **`isAstroDev`** (virtual module) | `import.meta.env.DEV` — Vite’s compile-time flag for components. Layer selection still comes from `environments` / `forceEnvironment`; use `isAstroDev` when you need Astro’s literal dev detection. |
|
|
32
|
+
|
|
33
|
+
You cannot add an environment key named **`dev`** — that name is reserved and merged automatically (including its `when`; you do not set it in config).
|
|
34
|
+
|
|
35
|
+
## Quickstart
|
|
36
|
+
|
|
37
|
+
1. Configure in `astro.config.mjs`:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
import astroFeatureFlags from "@at-flux/astro-feature-flags";
|
|
41
|
+
|
|
42
|
+
export default defineConfig({
|
|
43
|
+
integrations: [
|
|
44
|
+
astroFeatureFlags({
|
|
45
|
+
// optional: jsonConfigPath: "./ff.json",
|
|
46
|
+
// optional: configRoot: fileURLToPath(new URL(".", import.meta.url)),
|
|
47
|
+
flags: {
|
|
48
|
+
wip: {
|
|
49
|
+
colour: "rgb(220 38 38)",
|
|
50
|
+
routes: ["/blog/*"],
|
|
51
|
+
},
|
|
52
|
+
hotFeature1: {
|
|
53
|
+
colour: "rgb(37 99 235)",
|
|
54
|
+
routes: ["/hot-feature-1/*"],
|
|
55
|
+
},
|
|
56
|
+
hotFeature2: {
|
|
57
|
+
colour: "rgb(34 197 94)",
|
|
58
|
+
outline: false,
|
|
59
|
+
badge: true,
|
|
60
|
+
routes: ["/hot/*", "/hot-dev/*"],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
environments: {
|
|
64
|
+
prod: {
|
|
65
|
+
when: process.env.NODE_ENV === "production",
|
|
66
|
+
flags: {
|
|
67
|
+
wip: false,
|
|
68
|
+
hotFeature1: true,
|
|
69
|
+
hotFeature2: false,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
2. Optional JSON: **`jsonConfigPath`** on the integration root (merged after inline config). Optional **`jsonConfigPath`** on each **non-`dev`** environment merges when that layer is active (after the root file). Paths resolve relative to `configRoot` (`process.cwd()` by default).
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"environments": {
|
|
83
|
+
"prod": {
|
|
84
|
+
"flags": { "hotFeature1": false }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
3. Gate elements in markup:
|
|
91
|
+
- `data-ff={FeatureToken.HotFeature2}`
|
|
92
|
+
- `data-ff={[FeatureToken.Wip, FeatureToken.HotFeature2].join(' ')}`
|
|
93
|
+
- `data-ff="wip hot-feature-2"` **(no import!)**
|
|
94
|
+
- `data-ff-wip` **(no import!)**
|
|
95
|
+
- `data-ff-hot-feature-2` **(no import!)**
|
|
96
|
+
|
|
97
|
+
> [!NOTE]
|
|
98
|
+
> Flags are combinatory. If an element has `data-ff="wip hot-feature-2"`, both flags must be enabled for SSR outside the reserved `dev` layer.
|
|
99
|
+
>
|
|
100
|
+
> In the dev toolbar preview, combined flags are also combinatory for **Enabled**: if any token in the combo is set to Off, the whole combined element is hidden.
|
|
101
|
+
>
|
|
102
|
+
> In **Astro dev**, all declared flags are on at resolve time; the dev toolbar only changes client preview. In **non-dev** builds, nodes that fail the check are **removed from the HTML**. Route-mapped prefixes with a flag **off** are pruned from static `dist/` after build. Prefer **`shouldRenderFeature`** when you need compile-time omission with no trace in `dist/`.
|
|
103
|
+
|
|
104
|
+
## Common Use Cases
|
|
105
|
+
|
|
106
|
+
### 1) Per-element token (imported)
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
---
|
|
110
|
+
import { FeatureToken } from 'virtual:astro-feature-flags';
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
<section data-ff={FeatureToken.Wip}>WIP section</section>
|
|
114
|
+
<aside data-ff={FeatureToken.HotFeature2}>Hot section</aside>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
You can also use flag names in `data-ff`:
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
---
|
|
121
|
+
import { FeatureFlag } from 'virtual:astro-feature-flags';
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
<aside data-ff={FeatureFlag.HotFeature2}>Hot section</aside>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 2) Shorthand attribute (no import)
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
<section data-ff-wip>WIP section</section>
|
|
131
|
+
<aside data-ff-hot-feature-2>Hot section</aside>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`data-ff-wip` is equivalent to `data-ff={FeatureToken.Wip}` or `data-ff="wip"`.
|
|
135
|
+
|
|
136
|
+
If `tokenNamespace` is `aff`, use `data-aff` / `data-aff-<token>` instead.
|
|
137
|
+
|
|
138
|
+
### 2b) Combined flags (AND behavior)
|
|
139
|
+
|
|
140
|
+
Both flags must be enabled:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
<div data-ff-wip data-ff-hot-feature-2>
|
|
144
|
+
...
|
|
145
|
+
</div>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Or using `data-ff` with values:
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
---
|
|
152
|
+
import { FeatureFlag } from 'virtual:astro-feature-flags';
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
<div data-ff={[FeatureFlag.Wip, FeatureFlag.HotFeature2].join(' ')}>...</div>
|
|
156
|
+
// OR
|
|
157
|
+
<div data-ff="wip hot-feature-2">...</div>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`data-ff` expects a space-separated list of feature flags.
|
|
161
|
+
|
|
162
|
+
### 3) Dev toolbar head injection (automatic)
|
|
163
|
+
|
|
164
|
+
On **`astro dev`**, when the built-in dev layer is active, the integration uses Astro’s **`injectScript('head-inline', …)`** to append dev-only CSS, set **`data-ff-route`** on `<html>` from the current URL (including after **`astro:page-load`** / **`astro:after-swap`**), and run the toolbar bootstrap script. You do **not** need to wire `affDevBootstrap`, `featureFlagStyles`, or `data-ff-route` in a root layout unless you intentionally want a second copy.
|
|
165
|
+
|
|
166
|
+
The virtual module still exports **`affDevBootstrap`**, **`featureFlagStyles`**, and **`routeFeatureTokensForPath`** for advanced layouts.
|
|
167
|
+
|
|
168
|
+
### 4) Logic usage (`FeatureFlag`)
|
|
169
|
+
|
|
170
|
+
Use this when you need explicit conditional logic in frontmatter (most UI cases can stay markup-only with `data-ff-*`):
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { FeatureFlag, shouldRenderFeature } from "virtual:astro-feature-flags";
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`shouldRenderFeature()` and `isFeatureEnabled()` follow config/env values.\
|
|
177
|
+
The dev toolbar changes client-side preview state only.
|
|
178
|
+
|
|
179
|
+
## Configuration Schema
|
|
180
|
+
|
|
181
|
+
### Top-level options
|
|
182
|
+
|
|
183
|
+
| Option | Type | Default | Notes |
|
|
184
|
+
| ------------------ | ----------------------------------- | --------------- | --------------------------------------------------------------------- |
|
|
185
|
+
| `configRoot` | `string` | `process.cwd()` | Resolves relative `jsonConfigPath` values (root + per-environment). |
|
|
186
|
+
| `jsonConfigPath` | `string` | unset | Optional **root** JSON file merged after inline config (see merge order for per-environment files). |
|
|
187
|
+
| `forceEnvironment` | `string` | unset | Pin the active layer (skips `when` / `AFF_ENVIRONMENT` validation). |
|
|
188
|
+
| `mode` | `string` | `NODE_ENV` | Optional advanced override for runtime resolution (mainly tests/tooling). Most apps should omit this and rely on `NODE_ENV` + `environments.when`. |
|
|
189
|
+
| `env` | `Record<string, string \| undefined>` | `process.env` | `AFF_FEATURE_*` / `ASTRO_FEATURE_FLAGS` (not applied in `dev` layer). |
|
|
190
|
+
| `tokenNamespace` | `string` | `'ff'` | CSS var namespace (`--ff-c-*`). |
|
|
191
|
+
| `flags` | `Record<string, FlagConfig>` | `{}` | Flag declarations. |
|
|
192
|
+
| `environments` | `Record<string, EnvironmentConfig>` | _(see below)_ | Declare non-`dev` layers only; reserved `dev` is injected. At least one other key; exactly one `when: true` unless forced. |
|
|
193
|
+
| `css` | `DevOutlineCssOptions` | defaults | Global badge/outline layout and styling. |
|
|
194
|
+
| `staticMinify` | `boolean` | `true` | For static builds: route-prune disabled prefixes + cull gated HTML in `dist/`. Set `false` to keep emitted files untouched. |
|
|
195
|
+
|
|
196
|
+
If you omit `environments`, the integration injects a minimal reserved `dev` plus **`prod`** tied to `NODE_ENV` (or `mode` only if you explicitly override it) so `astroFeatureFlags()` still runs in small demos.
|
|
197
|
+
|
|
198
|
+
### Reserved name `dev`
|
|
199
|
+
|
|
200
|
+
The key **`dev`** is reserved: do not list it under `environments`. The integration injects it with `when: mode !== "production"` (mode defaults to `NODE_ENV`) so local **`astro dev`** uses the all-flags-on layer. Configure only shipped layers (`prod`, `staging`, …) yourself.
|
|
201
|
+
|
|
202
|
+
### `FlagConfig`
|
|
203
|
+
|
|
204
|
+
| Field | Type | Default | Notes |
|
|
205
|
+
| ------------------ | ---------- | ------------------ | ----------------------------------------- |
|
|
206
|
+
| `colour` / `color` | `string` | inherited fallback | Outline/badge color. |
|
|
207
|
+
| `routes` | `string[]` | `[]` | Route wildcard mapping (`/x/*`, `/x/**`). |
|
|
208
|
+
| `outline` | `boolean` | `true` | Default toolbar outline state in dev. |
|
|
209
|
+
| `badge` | `boolean` | `true` | Default toolbar badge state in dev. |
|
|
210
|
+
|
|
211
|
+
### `EnvironmentConfig`
|
|
212
|
+
|
|
213
|
+
| Field | Type | Default | Notes |
|
|
214
|
+
| ---------------- | ------------------------- | ------- | --------------------------------------------------------------------- |
|
|
215
|
+
| `when` | `boolean` | unset | Exactly one environment must have `when: true` (unless forced). |
|
|
216
|
+
| `flags` | `Record<string, boolean>` | `{}` | For non-`dev` layers: booleans per flag. Ignored for reserved `dev`. |
|
|
217
|
+
| `jsonConfigPath` | `string` | unset | Optional JSON merged when this environment is the active layer (not used on reserved `dev`). |
|
|
218
|
+
|
|
219
|
+
Merge order:
|
|
220
|
+
|
|
221
|
+
1. Inline config in `astro.config.mjs`
|
|
222
|
+
2. Root `jsonConfigPath` (if set)
|
|
223
|
+
3. `environments.<active>.jsonConfigPath` (if set; skipped for `dev`)
|
|
224
|
+
4. Process overrides on non-`dev` layers: `AFF_FEATURE_*`, then `ASTRO_FEATURE_FLAGS`
|
|
225
|
+
|
|
226
|
+
Layer select override: `AFF_ENVIRONMENT=prod`. **`forceEnvironment`** on the integration options wins over **`AFF_ENVIRONMENT`** when both are set, and skips the “exactly one `when: true`” check by pinning the layer directly. In static builds, changing `AFF_ENVIRONMENT` after build does nothing unless you rebuild (or disable `staticMinify` and use a server runtime that evaluates flags at request time).
|
|
227
|
+
|
|
228
|
+
### DevOutlineCssOptions
|
|
229
|
+
|
|
230
|
+
| Field | Default | Meaning |
|
|
231
|
+
| ------------------------------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
232
|
+
| `elementBadgeHorizontalAlign` | `'end'` | `'start'` \| `'center'` \| `'end'` — LTR: **`end`** = top-right. |
|
|
233
|
+
| `elementBadgeHorizontalPercent` | _(unset)_ | 0–100: horizontal anchor with pill centred (`translateX(-50%)`); overrides align. |
|
|
234
|
+
| `elementBadgeVerticalShiftPercent` | `80` | Vertical shift as **% of the pill height** (default keeps most of the label above the element). |
|
|
235
|
+
| `elementBadgeVerticalAnchor` | `'top'` | `'top'` or `'bottom'`. |
|
|
236
|
+
|
|
237
|
+
Per-element badge overrides (markup):
|
|
238
|
+
|
|
239
|
+
- `data-ff-align="start|center|end"`
|
|
240
|
+
- `data-ff-horizontal="50"`
|
|
241
|
+
- `data-ff-vertical="100"`
|
|
242
|
+
- `data-ff-anchor="top|bottom"`
|
|
243
|
+
|
|
244
|
+
See `example/src/pages/hot-feature-1/index.astro` for all three position controls in use.
|
|
245
|
+
|
|
246
|
+
## TypeScript
|
|
247
|
+
|
|
248
|
+
Astro projects typically pick this up automatically from package exports.
|
|
249
|
+
If your editor misses virtual module types, add one reference in `src/env.d.ts`.
|
|
250
|
+
|
|
251
|
+
## Dev toolbar
|
|
252
|
+
|
|
253
|
+
| Control | Effect |
|
|
254
|
+
| ----------- | ------------------------------------------------------ |
|
|
255
|
+
| **Enabled** | Off → hide nodes carrying that token in `data-ff` (including combined hosts/pages when any member token is Off). |
|
|
256
|
+
| **Outline** | Toggle outlines only (element and route frame). For combined hosts this is a non-layout-shifting overlay ring. |
|
|
257
|
+
| **Badges** | Toggle badges only (element pills + route pill). |
|
|
258
|
+
| **Colour** | `--<namespace>-c-<token>` (persisted). |
|
|
259
|
+
|
|
260
|
+
## Virtual module
|
|
261
|
+
|
|
262
|
+
Exports include **`FeatureFlag`**, **`FeatureToken`**, **`isAstroDev`**, **`activeEnvironmentKey`**, **`defaultNonDevEnvironment`**, **`flagsForEnvironment`**, **`isFeatureEnabledForEnvironment`**, **`shouldIncludePathForEnvironment`**, **`affDevBootstrap`**, **`routeFeatureTokenForPath`**, **`routeFeatureTokensForPath`**, **`shouldRenderFeature`**, **`matchedFeatureRoutePrefix`**, **`featureFlagStyles`**, etc.
|
|
263
|
+
|
|
264
|
+
**Programmatic resolution**: `getResolvedFeatures(config)` / `resolveFeatureRuntime(config)` use the same rules as the integration. Set **`forceEnvironment: "prod"`** (or any other key) to pin a layer (e.g. sitemaps generated while `astro` is in dev but routes should match a shipped layer).
|
|
265
|
+
|
|
266
|
+
**`featureFlagStyles`**: dev-only (outlines, badges, route badges, route-prune overlay). In production it is always an **empty string** — static HTML is cleaned up after build instead. You can still import it so a shared layout keeps one code path; empty `<style>` tags are removed from emitted HTML.
|
|
267
|
+
|
|
268
|
+
**`featureFlagsByEnvironment`**: frozen map of resolved booleans per `environments` key. The dev bootstrap compares the current URL against each layer and lists which keys would omit that route.
|
|
269
|
+
|
|
270
|
+
**`defaultNonDevEnvironment`**: prefers `prod` if defined, otherwise the first non-`dev` key (sorted). Use with **`shouldIncludePathForEnvironment(path, defaultNonDevEnvironment)`** (or any explicit key) when you want “primary shipped layer” without hard-coding a name — your non-dev keys can be `staging`, `preview-123`, etc.
|
|
271
|
+
|
|
272
|
+
## What this package is not
|
|
273
|
+
|
|
274
|
+
Remote percentage rollouts, per-user experiment assignment, analytics, or a hosted flag service. This is **declarative Astro config** + build-time HTML cleanup + a **local dev toolbar**.
|
|
275
|
+
|
|
276
|
+
## How-to
|
|
277
|
+
|
|
278
|
+
- `docs/how-to/hide-from-sitemaps.md`
|
|
279
|
+
|
|
280
|
+
## Example Pages
|
|
281
|
+
|
|
282
|
+
`example/` — `pnpm install && pnpm dev`.
|
|
283
|
+
|
|
284
|
+
- `/` integration overview + tagging options
|
|
285
|
+
- `/hot-feature-1/` route mapped to `hotFeature1`
|
|
286
|
+
- `/hot/` route mapped to `hotFeature2`
|
|
287
|
+
- `/hot-dev/sub/` wildcard nested route + combined `wip` + `hotFeature2` element gating
|
|
288
|
+
|
|
289
|
+
## Tests
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
pnpm test
|
|
293
|
+
pnpm typecheck
|
|
294
|
+
ENABLE_SLOW=1 pnpm test
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Slow checks that run a real `example` production build plus a small fixture (route pruning, `shouldRenderFeature`, and `data-ff` HTML culling) are documented in [docs/testing.md](./docs/testing.md). Enable them with `ENABLE_SLOW=1`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DevToolbarApp } from "astro";
|
|
2
|
+
|
|
3
|
+
//#region src/dev-toolbar-app.d.ts
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
__AFF__?: {
|
|
7
|
+
tokens: string[];
|
|
8
|
+
colors?: Record<string, string>;
|
|
9
|
+
namespace?: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
declare const affDevToolbarApp: DevToolbarApp;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { affDevToolbarApp as default };
|
|
16
|
+
//# sourceMappingURL=dev-toolbar-app.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-toolbar-app.d.mts","names":[],"sources":["../src/dev-toolbar-app.ts"],"mappings":";;;QASQ,MAAA;EAAA,UACI,MAAA;IACR,OAAA;MACE,MAAA;MACA,MAAA,GAAS,MAAA;MACT,SAAA;IAAA;EAAA;AAAA;AAAA,cAqHA,gBAAA,EAAkB,aAAA"}
|