@ops-ai/toggly-docusaurus-plugin 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +235 -0
- package/dist/client/index.d.ts +82 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +126 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/setup.d.ts +10 -0
- package/dist/client/setup.d.ts.map +1 -0
- package/dist/client/setup.js +18 -0
- package/dist/client/setup.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +193 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# @ops-ai/toggly-docusaurus-plugin
|
|
2
|
+
|
|
3
|
+
Docusaurus plugin and React bindings for gating documentation content with Toggly feature flags.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @ops-ai/toggly-docusaurus-plugin @ops-ai/toggly-client-core
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @ops-ai/toggly-docusaurus-plugin @ops-ai/toggly-client-core
|
|
11
|
+
# or
|
|
12
|
+
yarn add @ops-ai/toggly-docusaurus-plugin @ops-ai/toggly-client-core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
Add the plugin to your `docusaurus.config.js` or `docusaurus.config.ts`:
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
// docusaurus.config.js
|
|
21
|
+
module.exports = {
|
|
22
|
+
// ... other config
|
|
23
|
+
plugins: [
|
|
24
|
+
[
|
|
25
|
+
'@ops-ai/toggly-docusaurus-plugin',
|
|
26
|
+
{
|
|
27
|
+
baseURI: 'https://client.toggly.io',
|
|
28
|
+
appKey: 'your-app-key',
|
|
29
|
+
environment: 'Production',
|
|
30
|
+
flagDefaults: {
|
|
31
|
+
'beta-feature': false,
|
|
32
|
+
},
|
|
33
|
+
featureFlagsRefreshInterval: 180000, // 3 minutes
|
|
34
|
+
isDebug: false,
|
|
35
|
+
connectTimeout: 5000,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Plugin Options
|
|
43
|
+
|
|
44
|
+
- `baseURI` (string, optional): Base URI for the Toggly API (default: `'https://client.toggly.io'`)
|
|
45
|
+
- `appKey` (string, optional): Application key from Toggly
|
|
46
|
+
- `environment` (string, optional): Environment name (default: `'Production'`)
|
|
47
|
+
- `flagDefaults` (object, optional): Default flag values when API is unavailable
|
|
48
|
+
- `featureFlagsRefreshInterval` (number, optional): Refresh interval in milliseconds (default: `180000` = 3 minutes)
|
|
49
|
+
- `isDebug` (boolean, optional): Enable debug logging (default: `false`)
|
|
50
|
+
- `connectTimeout` (number, optional): Connection timeout in milliseconds (default: `5000`)
|
|
51
|
+
- `identity` (string, optional): User identity for targeting
|
|
52
|
+
|
|
53
|
+
## Page-Level Gating
|
|
54
|
+
|
|
55
|
+
Add `x-feature` to the frontmatter of any MD/MDX file to gate the entire page:
|
|
56
|
+
|
|
57
|
+
```markdown
|
|
58
|
+
---
|
|
59
|
+
id: sso-setup
|
|
60
|
+
title: Single Sign-On Setup
|
|
61
|
+
x-feature: enterprise_sso
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
This page is only visible when the `enterprise_sso` feature flag is enabled.
|
|
65
|
+
|
|
66
|
+
The Cloudflare Worker will gate this page according to the `enterprise_sso` flag.
|
|
67
|
+
If the feature is off, the page will return a 404 (or redirect, depending on Worker configuration).
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### How It Works
|
|
71
|
+
|
|
72
|
+
1. **During Build**: The plugin inspects each doc's metadata and extracts the `x-feature` frontmatter property
|
|
73
|
+
2. **Route Mapping**: It creates a mapping from the doc's route path (e.g., `/docs/enterprise/sso-setup`) to the feature key (e.g., `enterprise_sso`)
|
|
74
|
+
3. **Manifest Generation**: At the end of the build, it emits a JSON file at `${outDir}/toggly-page-features.json` in the build output directory
|
|
75
|
+
4. **Edge Enforcement**: The Cloudflare Worker reads this manifest and enforces gating at the edge
|
|
76
|
+
|
|
77
|
+
### Generated Manifest
|
|
78
|
+
|
|
79
|
+
The plugin automatically generates a JSON manifest in your build output directory:
|
|
80
|
+
|
|
81
|
+
**Location**: `build/toggly-page-features.json` (or `${outDir}/toggly-page-features.json`)
|
|
82
|
+
|
|
83
|
+
**Example content**:
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"/docs/enterprise/sso-setup": "enterprise_sso",
|
|
87
|
+
"/docs/advanced/filters": "beta_advanced_filters"
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
This manifest is consumed by the Cloudflare Worker to determine which pages should be gated and which feature flag to check for each route.
|
|
92
|
+
|
|
93
|
+
## React Components and Hooks
|
|
94
|
+
|
|
95
|
+
### Setup TogglyProvider
|
|
96
|
+
|
|
97
|
+
Wrap your Docusaurus app with `TogglyProvider`. You can do this by swizzling the root layout:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm run swizzle @docusaurus/theme-classic Root -- --wrap
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Then modify `src/theme/Root/index.js`:
|
|
104
|
+
|
|
105
|
+
```jsx
|
|
106
|
+
import React from 'react';
|
|
107
|
+
import Root from '@theme/Root';
|
|
108
|
+
import { TogglyProvider } from '@ops-ai/toggly-docusaurus-plugin/client';
|
|
109
|
+
|
|
110
|
+
export default function RootWrapper({ children }) {
|
|
111
|
+
// Config is automatically injected by the plugin
|
|
112
|
+
const config = typeof window !== 'undefined' ? window.__TOGGLY_CONFIG__ : {};
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<TogglyProvider config={config}>
|
|
116
|
+
<Root>{children}</Root>
|
|
117
|
+
</TogglyProvider>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Using the Feature Component
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
import { Feature } from '@ops-ai/toggly-docusaurus-plugin/client';
|
|
126
|
+
|
|
127
|
+
function MyComponent() {
|
|
128
|
+
return (
|
|
129
|
+
<div>
|
|
130
|
+
<h1>Public Content</h1>
|
|
131
|
+
|
|
132
|
+
<Feature flag="beta_advanced_filters" fallback={<p>This feature is coming soon!</p>}>
|
|
133
|
+
<h2>Advanced Filters (Beta)</h2>
|
|
134
|
+
<p>This feature is in beta...</p>
|
|
135
|
+
</Feature>
|
|
136
|
+
</div>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Using the useFlag Hook
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
import { useFlag } from '@ops-ai/toggly-docusaurus-plugin/client';
|
|
145
|
+
|
|
146
|
+
function MyComponent() {
|
|
147
|
+
const { enabled, isReady } = useFlag('beta_advanced_filters', false);
|
|
148
|
+
|
|
149
|
+
if (!isReady) {
|
|
150
|
+
return <div>Loading...</div>;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return enabled ? (
|
|
154
|
+
<div>Beta feature is enabled!</div>
|
|
155
|
+
) : (
|
|
156
|
+
<div>Beta feature is disabled</div>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Using the useToggly Hook
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
import { useToggly } from '@ops-ai/toggly-docusaurus-plugin/client';
|
|
165
|
+
|
|
166
|
+
function MyComponent() {
|
|
167
|
+
const { flags, isReady, getFlag } = useToggly();
|
|
168
|
+
|
|
169
|
+
const handleClick = async () => {
|
|
170
|
+
const isEnabled = await getFlag('my-feature', false);
|
|
171
|
+
console.log('Feature enabled:', isEnabled);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<button onClick={handleClick} disabled={!isReady}>
|
|
176
|
+
Check Feature
|
|
177
|
+
</button>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Section-Level Gating
|
|
183
|
+
|
|
184
|
+
For section-level gating, you can use the `data-feature` attribute with a client-side script or component:
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
import { useFlag } from '@ops-ai/toggly-docusaurus-plugin/client';
|
|
188
|
+
|
|
189
|
+
function FeatureSection({ flag, children }) {
|
|
190
|
+
const { enabled, isReady } = useFlag(flag);
|
|
191
|
+
|
|
192
|
+
if (!isReady || !enabled) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return <div data-feature={flag}>{children}</div>;
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Or in MDX:
|
|
201
|
+
|
|
202
|
+
```mdx
|
|
203
|
+
import { Feature } from '@ops-ai/toggly-docusaurus-plugin/client';
|
|
204
|
+
|
|
205
|
+
<Feature flag="beta_advanced_filters">
|
|
206
|
+
<div data-feature="beta_advanced_filters">
|
|
207
|
+
<h2>Advanced Filters (Beta)</h2>
|
|
208
|
+
<p>This section is gated by the feature flag.</p>
|
|
209
|
+
</div>
|
|
210
|
+
</Feature>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Generated Files
|
|
214
|
+
|
|
215
|
+
The plugin generates:
|
|
216
|
+
|
|
217
|
+
- `build/toggly-page-features.json` (or `${outDir}/toggly-page-features.json`): A mapping of route paths to feature flag keys, used by the Cloudflare Worker for edge enforcement
|
|
218
|
+
|
|
219
|
+
This file is generated during the Docusaurus build process and is placed in the build output directory, making it accessible to the Cloudflare Worker at the root of your deployed site.
|
|
220
|
+
|
|
221
|
+
## TypeScript Support
|
|
222
|
+
|
|
223
|
+
Full TypeScript support is included. Import types as needed:
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
import type {
|
|
227
|
+
TogglyProviderProps,
|
|
228
|
+
TogglyContextValue,
|
|
229
|
+
FeatureProps,
|
|
230
|
+
} from '@toggly/docusaurus-plugin/client';
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## License
|
|
234
|
+
|
|
235
|
+
MIT
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React client bindings for Toggly in Docusaurus
|
|
3
|
+
*
|
|
4
|
+
* Provides React context, hooks, and components for feature flag evaluation
|
|
5
|
+
*/
|
|
6
|
+
import { ReactNode } from 'react';
|
|
7
|
+
import { type TogglyConfig, type Flags } from '@toggly/client-core';
|
|
8
|
+
export interface TogglyProviderProps {
|
|
9
|
+
config: TogglyConfig;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export interface TogglyContextValue {
|
|
13
|
+
flags: Flags;
|
|
14
|
+
isReady: boolean;
|
|
15
|
+
getFlag: (key: string, defaultValue?: boolean) => Promise<boolean>;
|
|
16
|
+
error: Error | null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* TogglyProvider - React context provider for Toggly feature flags
|
|
20
|
+
*
|
|
21
|
+
* Wrap your Docusaurus app with this provider to enable feature flag evaluation.
|
|
22
|
+
* The config can be read from window.__TOGGLY_CONFIG__ (injected by the plugin)
|
|
23
|
+
* or passed directly.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // Option 1: Read from window (recommended)
|
|
28
|
+
* const config = (window as any).__TOGGLY_CONFIG__ || {};
|
|
29
|
+
* <TogglyProvider config={config}>
|
|
30
|
+
* {children}
|
|
31
|
+
* </TogglyProvider>
|
|
32
|
+
*
|
|
33
|
+
* // Option 2: Pass config directly
|
|
34
|
+
* <TogglyProvider config={{ appKey: '...', environment: 'Production' }}>
|
|
35
|
+
* {children}
|
|
36
|
+
* </TogglyProvider>
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function TogglyProvider({ config: providedConfig, children, }: TogglyProviderProps): JSX.Element;
|
|
40
|
+
/**
|
|
41
|
+
* useToggly - Hook to access Toggly context
|
|
42
|
+
*
|
|
43
|
+
* Returns the Toggly context value with flags and helper methods.
|
|
44
|
+
*/
|
|
45
|
+
export declare function useToggly(): TogglyContextValue;
|
|
46
|
+
/**
|
|
47
|
+
* useFlag - Hook to check if a feature flag is enabled
|
|
48
|
+
*
|
|
49
|
+
* @param flagKey - The key of the feature flag to check
|
|
50
|
+
* @param defaultValue - Optional default value if flag is not found
|
|
51
|
+
* @returns Object with enabled state and ready state
|
|
52
|
+
*/
|
|
53
|
+
export declare function useFlag(flagKey: string, defaultValue?: boolean): {
|
|
54
|
+
enabled: boolean;
|
|
55
|
+
isReady: boolean;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Feature component - Conditionally renders children based on feature flag
|
|
59
|
+
*/
|
|
60
|
+
export interface FeatureProps {
|
|
61
|
+
/** The feature flag key to check */
|
|
62
|
+
flag: string;
|
|
63
|
+
/** Content to render when flag is enabled */
|
|
64
|
+
children: ReactNode;
|
|
65
|
+
/** Content to render when flag is disabled (optional) */
|
|
66
|
+
fallback?: ReactNode;
|
|
67
|
+
/** Default value if flag is not found (default: false) */
|
|
68
|
+
defaultValue?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Feature - React component for conditional rendering based on feature flags
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```tsx
|
|
75
|
+
* <Feature flag="beta_advanced_filters">
|
|
76
|
+
* <h2>Advanced Filters (Beta)</h2>
|
|
77
|
+
* <p>This feature is in beta...</p>
|
|
78
|
+
* </Feature>
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export declare function Feature({ flag, children, fallback, defaultValue, }: FeatureProps): JSX.Element;
|
|
82
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAc,EAKZ,SAAS,EACV,MAAM,OAAO,CAAC;AACf,OAAO,EAAsB,KAAK,YAAY,EAAE,KAAK,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAExF,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EAAE,cAAc,EACtB,QAAQ,GACT,EAAE,mBAAmB,GAAG,GAAG,CAAC,OAAO,CAgDnC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,kBAAkB,CAM9C;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CACrB,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,OAAO,GACrB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAiBxC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,QAAQ,EAAE,SAAS,CAAC;IACpB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,QAAQ,EACR,QAAe,EACf,YAAoB,GACrB,EAAE,YAAY,GAAG,GAAG,CAAC,OAAO,CAS5B"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* React client bindings for Toggly in Docusaurus
|
|
4
|
+
*
|
|
5
|
+
* Provides React context, hooks, and components for feature flag evaluation
|
|
6
|
+
*/
|
|
7
|
+
import { createContext, useContext, useState, useEffect, } from 'react';
|
|
8
|
+
import { createTogglyClient } from '@toggly/client-core';
|
|
9
|
+
const TogglyContext = createContext(null);
|
|
10
|
+
/**
|
|
11
|
+
* TogglyProvider - React context provider for Toggly feature flags
|
|
12
|
+
*
|
|
13
|
+
* Wrap your Docusaurus app with this provider to enable feature flag evaluation.
|
|
14
|
+
* The config can be read from window.__TOGGLY_CONFIG__ (injected by the plugin)
|
|
15
|
+
* or passed directly.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* // Option 1: Read from window (recommended)
|
|
20
|
+
* const config = (window as any).__TOGGLY_CONFIG__ || {};
|
|
21
|
+
* <TogglyProvider config={config}>
|
|
22
|
+
* {children}
|
|
23
|
+
* </TogglyProvider>
|
|
24
|
+
*
|
|
25
|
+
* // Option 2: Pass config directly
|
|
26
|
+
* <TogglyProvider config={{ appKey: '...', environment: 'Production' }}>
|
|
27
|
+
* {children}
|
|
28
|
+
* </TogglyProvider>
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function TogglyProvider({ config: providedConfig, children, }) {
|
|
32
|
+
// If no config provided, try to read from window
|
|
33
|
+
const config = providedConfig ||
|
|
34
|
+
(typeof window !== 'undefined'
|
|
35
|
+
? window.__TOGGLY_CONFIG__ || {}
|
|
36
|
+
: {});
|
|
37
|
+
const [client] = useState(() => {
|
|
38
|
+
// Ensure we have a valid config
|
|
39
|
+
if (!config || (!config.appKey && Object.keys(config).length === 0)) {
|
|
40
|
+
console.warn('[Toggly] No config provided. Please configure the plugin in docusaurus.config.js or pass config to TogglyProvider');
|
|
41
|
+
}
|
|
42
|
+
return createTogglyClient(config);
|
|
43
|
+
});
|
|
44
|
+
const [flags, setFlags] = useState({});
|
|
45
|
+
const [isReady, setIsReady] = useState(false);
|
|
46
|
+
const [error, setError] = useState(null);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
// Initialize client and load flags
|
|
49
|
+
client
|
|
50
|
+
.getFlags()
|
|
51
|
+
.then((loadedFlags) => {
|
|
52
|
+
setFlags(loadedFlags);
|
|
53
|
+
setIsReady(true);
|
|
54
|
+
})
|
|
55
|
+
.catch((err) => {
|
|
56
|
+
setError(err);
|
|
57
|
+
setIsReady(true); // Still mark as ready even on error
|
|
58
|
+
});
|
|
59
|
+
}, [client]);
|
|
60
|
+
const getFlag = async (key, defaultValue) => {
|
|
61
|
+
return client.getFlag(key, defaultValue);
|
|
62
|
+
};
|
|
63
|
+
const value = {
|
|
64
|
+
flags,
|
|
65
|
+
isReady,
|
|
66
|
+
getFlag,
|
|
67
|
+
error,
|
|
68
|
+
};
|
|
69
|
+
return (_jsx(TogglyContext.Provider, { value: value, children: children }));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* useToggly - Hook to access Toggly context
|
|
73
|
+
*
|
|
74
|
+
* Returns the Toggly context value with flags and helper methods.
|
|
75
|
+
*/
|
|
76
|
+
export function useToggly() {
|
|
77
|
+
const context = useContext(TogglyContext);
|
|
78
|
+
if (!context) {
|
|
79
|
+
throw new Error('useToggly must be used within a TogglyProvider');
|
|
80
|
+
}
|
|
81
|
+
return context;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* useFlag - Hook to check if a feature flag is enabled
|
|
85
|
+
*
|
|
86
|
+
* @param flagKey - The key of the feature flag to check
|
|
87
|
+
* @param defaultValue - Optional default value if flag is not found
|
|
88
|
+
* @returns Object with enabled state and ready state
|
|
89
|
+
*/
|
|
90
|
+
export function useFlag(flagKey, defaultValue) {
|
|
91
|
+
const { flags, isReady, getFlag } = useToggly();
|
|
92
|
+
const [enabled, setEnabled] = useState(defaultValue ?? false);
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
if (isReady) {
|
|
95
|
+
// First check cached flags
|
|
96
|
+
if (flags[flagKey] !== undefined) {
|
|
97
|
+
setEnabled(flags[flagKey]);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// Fallback to async getFlag
|
|
101
|
+
getFlag(flagKey, defaultValue).then(setEnabled);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}, [flagKey, flags, isReady, getFlag, defaultValue]);
|
|
105
|
+
return { enabled, isReady };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Feature - React component for conditional rendering based on feature flags
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```tsx
|
|
112
|
+
* <Feature flag="beta_advanced_filters">
|
|
113
|
+
* <h2>Advanced Filters (Beta)</h2>
|
|
114
|
+
* <p>This feature is in beta...</p>
|
|
115
|
+
* </Feature>
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export function Feature({ flag, children, fallback = null, defaultValue = false, }) {
|
|
119
|
+
const { enabled, isReady } = useFlag(flag, defaultValue);
|
|
120
|
+
if (!isReady) {
|
|
121
|
+
// While loading, show nothing or a loading state
|
|
122
|
+
return _jsx(_Fragment, { children: fallback });
|
|
123
|
+
}
|
|
124
|
+
return _jsx(_Fragment, { children: enabled ? children : fallback });
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side setup for Toggly in Docusaurus
|
|
3
|
+
*
|
|
4
|
+
* This module runs in the browser and initializes the Toggly client.
|
|
5
|
+
* The config is available via window.__TOGGLY_CONFIG__ injected by the plugin.
|
|
6
|
+
*
|
|
7
|
+
* Note: Users need to wrap their app with TogglyProvider manually,
|
|
8
|
+
* or use the swizzle feature to inject it into the root layout.
|
|
9
|
+
*/
|
|
10
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/client/setup.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Client-side setup for Toggly in Docusaurus
|
|
4
|
+
*
|
|
5
|
+
* This module runs in the browser and initializes the Toggly client.
|
|
6
|
+
* The config is available via window.__TOGGLY_CONFIG__ injected by the plugin.
|
|
7
|
+
*
|
|
8
|
+
* Note: Users need to wrap their app with TogglyProvider manually,
|
|
9
|
+
* or use the swizzle feature to inject it into the root layout.
|
|
10
|
+
*/
|
|
11
|
+
// This module is imported globally by Docusaurus
|
|
12
|
+
// It can be used to set up global state or side effects
|
|
13
|
+
if (typeof window !== 'undefined') {
|
|
14
|
+
// Config is already available via window.__TOGGLY_CONFIG__ from injectHtmlTags
|
|
15
|
+
// Users can access it in their components via:
|
|
16
|
+
// const config = (window as any).__TOGGLY_CONFIG__;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/client/setup.tsx"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AAEH,iDAAiD;AACjD,wDAAwD;AAExD,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;IAClC,+EAA+E;IAC/E,+CAA+C;IAC/C,oDAAoD;AACtD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @toggly/docusaurus-plugin - Docusaurus plugin and React bindings
|
|
3
|
+
*
|
|
4
|
+
* Provides Docusaurus plugin integration and React components/hooks
|
|
5
|
+
* for gating documentation content with Toggly feature flags.
|
|
6
|
+
*/
|
|
7
|
+
import type { Plugin, LoadContext } from '@docusaurus/types';
|
|
8
|
+
export interface TogglyPluginOptions {
|
|
9
|
+
/** Base URI for the Toggly API (default: 'https://client.toggly.io') */
|
|
10
|
+
baseURI?: string;
|
|
11
|
+
/** Application key from Toggly */
|
|
12
|
+
appKey?: string;
|
|
13
|
+
/** Environment name (e.g., 'Production', 'Staging') (default: 'Production') */
|
|
14
|
+
environment?: string;
|
|
15
|
+
/** Default flag values to use when API is unavailable */
|
|
16
|
+
flagDefaults?: {
|
|
17
|
+
[key: string]: boolean;
|
|
18
|
+
};
|
|
19
|
+
/** Feature flags refresh interval in milliseconds (default: 180000 = 3 minutes) */
|
|
20
|
+
featureFlagsRefreshInterval?: number;
|
|
21
|
+
/** Enable debug logging (default: false) */
|
|
22
|
+
isDebug?: boolean;
|
|
23
|
+
/** Connection timeout in milliseconds (default: 5000) */
|
|
24
|
+
connectTimeout?: number;
|
|
25
|
+
/** User identity for targeting (optional) */
|
|
26
|
+
identity?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Docusaurus plugin for Toggly feature flag gating
|
|
30
|
+
*/
|
|
31
|
+
export default function togglyPlugin(context: LoadContext, options: TogglyPluginOptions): Plugin;
|
|
32
|
+
export { TogglyProvider, useToggly, useFlag, Feature } from './client';
|
|
33
|
+
export type { TogglyProviderProps, TogglyContextValue, FeatureProps, } from './client';
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAA8B,MAAM,mBAAmB,CAAC;AAMzF,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,YAAY,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAC1C,mFAAmF;IACnF,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,4CAA4C;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAmBD;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,mBAAmB,GAC3B,MAAM,CAqJR;AAmFD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACvE,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,GACb,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @toggly/docusaurus-plugin - Docusaurus plugin and React bindings
|
|
3
|
+
*
|
|
4
|
+
* Provides Docusaurus plugin integration and React components/hooks
|
|
5
|
+
* for gating documentation content with Toggly feature flags.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { glob } from 'glob';
|
|
10
|
+
import webpack from 'webpack';
|
|
11
|
+
/**
|
|
12
|
+
* Docusaurus plugin for Toggly feature flag gating
|
|
13
|
+
*/
|
|
14
|
+
export default function togglyPlugin(context, options) {
|
|
15
|
+
const { baseURI = 'https://client.toggly.io', appKey, environment = 'Production', flagDefaults = {}, featureFlagsRefreshInterval = 3 * 60 * 1000, isDebug = false, connectTimeout = 5 * 1000, identity, } = options;
|
|
16
|
+
// Store page feature mapping for postBuild
|
|
17
|
+
let pageFeatureMapping = {};
|
|
18
|
+
return {
|
|
19
|
+
name: 'toggly-plugin',
|
|
20
|
+
/**
|
|
21
|
+
* Load content: Extract x-feature frontmatter from docs
|
|
22
|
+
* We'll access doc metadata through the content system
|
|
23
|
+
*/
|
|
24
|
+
async loadContent() {
|
|
25
|
+
return {
|
|
26
|
+
config: {
|
|
27
|
+
baseURI,
|
|
28
|
+
appKey,
|
|
29
|
+
environment,
|
|
30
|
+
flagDefaults,
|
|
31
|
+
featureFlagsRefreshInterval,
|
|
32
|
+
isDebug,
|
|
33
|
+
connectTimeout,
|
|
34
|
+
identity,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* Content loaded: Extract x-feature from doc metadata and build route mapping
|
|
40
|
+
*/
|
|
41
|
+
async contentLoaded({ content, actions }) {
|
|
42
|
+
const { config: pluginConfig } = content;
|
|
43
|
+
// Extract page feature mapping from files
|
|
44
|
+
// We parse files directly to get x-feature frontmatter
|
|
45
|
+
// and will map to routes using Docusaurus's routing structure
|
|
46
|
+
pageFeatureMapping = await extractFromFiles(context);
|
|
47
|
+
// Store data for configureWebpack and postBuild
|
|
48
|
+
this.__togglyPluginData = {
|
|
49
|
+
pageFeatureMapping,
|
|
50
|
+
config: pluginConfig,
|
|
51
|
+
};
|
|
52
|
+
if (isDebug) {
|
|
53
|
+
console.log(`[Toggly Plugin] Found ${Object.keys(pageFeatureMapping).length} pages with x-feature frontmatter`);
|
|
54
|
+
if (Object.keys(pageFeatureMapping).length > 0) {
|
|
55
|
+
console.log('[Toggly Plugin] Page feature mappings:');
|
|
56
|
+
Object.entries(pageFeatureMapping).forEach(([route, feature]) => {
|
|
57
|
+
console.log(` ${route} -> ${feature}`);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
/**
|
|
63
|
+
* Post build: Write manifest to output directory
|
|
64
|
+
*/
|
|
65
|
+
async postBuild({ outDir }) {
|
|
66
|
+
const pluginData = this.__togglyPluginData;
|
|
67
|
+
if (!pluginData) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const { pageFeatureMapping: mapping } = pluginData;
|
|
71
|
+
// Write manifest to build output directory
|
|
72
|
+
const manifestPath = path.join(outDir, 'toggly-page-features.json');
|
|
73
|
+
fs.writeFileSync(manifestPath, JSON.stringify(mapping, null, 2), 'utf-8');
|
|
74
|
+
if (isDebug) {
|
|
75
|
+
console.log(`[Toggly Plugin] Generated page feature manifest: ${manifestPath}`);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
/**
|
|
79
|
+
* Configure Webpack: Inject Toggly config into client bundle
|
|
80
|
+
*/
|
|
81
|
+
configureWebpack(config, isServer) {
|
|
82
|
+
if (isServer) {
|
|
83
|
+
return {};
|
|
84
|
+
}
|
|
85
|
+
// Get stored data from contentLoaded
|
|
86
|
+
const pluginData = this.__togglyPluginData;
|
|
87
|
+
if (!pluginData) {
|
|
88
|
+
return {};
|
|
89
|
+
}
|
|
90
|
+
const { pageFeatureMapping, config: pluginConfig } = pluginData;
|
|
91
|
+
return {
|
|
92
|
+
plugins: [
|
|
93
|
+
new webpack.DefinePlugin({
|
|
94
|
+
__TOGGLY_CONFIG__: JSON.stringify(pluginConfig),
|
|
95
|
+
__TOGGLY_PAGE_FEATURES__: JSON.stringify(pageFeatureMapping),
|
|
96
|
+
}),
|
|
97
|
+
],
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
/**
|
|
101
|
+
* Inject HTML tags: Add script to make config available globally
|
|
102
|
+
*/
|
|
103
|
+
injectHtmlTags() {
|
|
104
|
+
const pluginData = this.__togglyPluginData;
|
|
105
|
+
if (!pluginData) {
|
|
106
|
+
return {};
|
|
107
|
+
}
|
|
108
|
+
const { config: pluginConfig } = pluginData;
|
|
109
|
+
return {
|
|
110
|
+
headTags: [
|
|
111
|
+
{
|
|
112
|
+
tagName: 'script',
|
|
113
|
+
innerHTML: `window.__TOGGLY_CONFIG__ = ${JSON.stringify(pluginConfig)};`,
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
},
|
|
118
|
+
/**
|
|
119
|
+
* Get client modules: Import the client setup module
|
|
120
|
+
*/
|
|
121
|
+
getClientModules() {
|
|
122
|
+
return [path.resolve(__dirname, './client/setup')];
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Extract page feature mapping by parsing files directly
|
|
128
|
+
* Maps file paths to Docusaurus route paths
|
|
129
|
+
*/
|
|
130
|
+
async function extractFromFiles(context) {
|
|
131
|
+
const { siteDir, baseUrl } = context;
|
|
132
|
+
const docsDir = path.join(siteDir, 'docs');
|
|
133
|
+
const pageFeatureMapping = {};
|
|
134
|
+
// Check if docs directory exists
|
|
135
|
+
if (!fs.existsSync(docsDir)) {
|
|
136
|
+
return pageFeatureMapping;
|
|
137
|
+
}
|
|
138
|
+
// Find all MD/MDX files in the docs directory
|
|
139
|
+
const files = await glob('**/*.{md,mdx}', {
|
|
140
|
+
cwd: docsDir,
|
|
141
|
+
absolute: false,
|
|
142
|
+
ignore: ['node_modules/**'],
|
|
143
|
+
});
|
|
144
|
+
for (const file of files) {
|
|
145
|
+
const filePath = path.join(docsDir, file);
|
|
146
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
147
|
+
// Extract frontmatter
|
|
148
|
+
const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
|
|
149
|
+
if (frontmatterMatch) {
|
|
150
|
+
const frontmatter = frontmatterMatch[1];
|
|
151
|
+
// Extract x-feature property (supports YAML with or without quotes)
|
|
152
|
+
const xFeatureMatch = frontmatter.match(/^x-feature:\s*(.+)$/m);
|
|
153
|
+
if (xFeatureMatch) {
|
|
154
|
+
let featureKey = xFeatureMatch[1].trim();
|
|
155
|
+
// Remove quotes if present
|
|
156
|
+
featureKey = featureKey.replace(/^["']|["']$/g, '');
|
|
157
|
+
// Convert file path to Docusaurus route path
|
|
158
|
+
// Docusaurus routes docs as: /docs/<path>
|
|
159
|
+
// File structure: docs/<category>/<file>.md -> /docs/<category>/<file>
|
|
160
|
+
let routePath = file.replace(/\.(md|mdx)$/, '').replace(/\\/g, '/');
|
|
161
|
+
// Handle index files - they become the parent directory route
|
|
162
|
+
if (path.basename(routePath) === 'index') {
|
|
163
|
+
routePath = path.dirname(routePath);
|
|
164
|
+
if (routePath === '.') {
|
|
165
|
+
routePath = '';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Ensure path starts with /
|
|
169
|
+
if (!routePath.startsWith('/')) {
|
|
170
|
+
routePath = '/' + routePath;
|
|
171
|
+
}
|
|
172
|
+
// Prepend /docs/ if not already there
|
|
173
|
+
if (!routePath.startsWith('/docs')) {
|
|
174
|
+
routePath = '/docs' + routePath;
|
|
175
|
+
}
|
|
176
|
+
// Remove trailing slash (except for root /docs)
|
|
177
|
+
routePath = routePath.replace(/\/$/, '') || '/docs';
|
|
178
|
+
// Prepend baseUrl if not root
|
|
179
|
+
// baseUrl is typically '/' but can be '/project-name/' for GitHub Pages
|
|
180
|
+
let fullRoutePath = routePath;
|
|
181
|
+
if (baseUrl !== '/') {
|
|
182
|
+
const normalizedBaseUrl = baseUrl.replace(/\/$/, '');
|
|
183
|
+
fullRoutePath = normalizedBaseUrl + routePath;
|
|
184
|
+
}
|
|
185
|
+
pageFeatureMapping[fullRoutePath] = featureKey;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return pageFeatureMapping;
|
|
190
|
+
}
|
|
191
|
+
// Export React components and hooks
|
|
192
|
+
export { TogglyProvider, useToggly, useFlag, Feature } from './client';
|
|
193
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,OAAO,MAAM,SAAS,CAAC;AAsC9B;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,OAAoB,EACpB,OAA4B;IAE5B,MAAM,EACJ,OAAO,GAAG,0BAA0B,EACpC,MAAM,EACN,WAAW,GAAG,YAAY,EAC1B,YAAY,GAAG,EAAE,EACjB,2BAA2B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,EAC3C,OAAO,GAAG,KAAK,EACf,cAAc,GAAG,CAAC,GAAG,IAAI,EACzB,QAAQ,GACT,GAAG,OAAO,CAAC;IAEZ,2CAA2C;IAC3C,IAAI,kBAAkB,GAAuB,EAAE,CAAC;IAEhD,OAAO;QACL,IAAI,EAAE,eAAe;QAErB;;;WAGG;QACH,KAAK,CAAC,WAAW;YACf,OAAO;gBACL,MAAM,EAAE;oBACN,OAAO;oBACP,MAAM;oBACN,WAAW;oBACX,YAAY;oBACZ,2BAA2B;oBAC3B,OAAO;oBACP,cAAc;oBACd,QAAQ;iBACT;aACF,CAAC;QACJ,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE;YACtC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,OAEhC,CAAC;YAEF,0CAA0C;YAC1C,uDAAuD;YACvD,8DAA8D;YAC9D,kBAAkB,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;YAErD,gDAAgD;YAC/C,IAAY,CAAC,kBAAkB,GAAG;gBACjC,kBAAkB;gBAClB,MAAM,EAAE,YAAY;aACrB,CAAC;YAEF,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,GAAG,CACT,yBAAyB,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,MAAM,mCAAmC,CACnG,CAAC;gBACF,IAAI,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC/C,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;oBACtD,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE;wBAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,OAAO,OAAO,EAAE,CAAC,CAAC;oBAC1C,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE;YACxB,MAAM,UAAU,GAAI,IAAY,CAAC,kBAAkB,CAAC;YACpD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO;YACT,CAAC;YAED,MAAM,EAAE,kBAAkB,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;YAEnD,2CAA2C;YAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;YACpE,EAAE,CAAC,aAAa,CACd,YAAY,EACZ,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAChC,OAAO,CACR,CAAC;YAEF,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,GAAG,CACT,oDAAoD,YAAY,EAAE,CACnE,CAAC;YACJ,CAAC;QACH,CAAC;QAED;;WAEG;QACH,gBAAgB,CAAC,MAAM,EAAE,QAAQ;YAC/B,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,qCAAqC;YACrC,MAAM,UAAU,GAAI,IAAY,CAAC,kBAAkB,CAAC;YACpD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,UAAU,CAAC;YAEhE,OAAO;gBACL,OAAO,EAAE;oBACP,IAAI,OAAO,CAAC,YAAY,CAAC;wBACvB,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;wBAC/C,wBAAwB,EAAE,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC;qBAC7D,CAAC;iBACH;aACF,CAAC;QACJ,CAAC;QAED;;WAEG;QACH,cAAc;YACZ,MAAM,UAAU,GAAI,IAAY,CAAC,kBAAkB,CAAC;YACpD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,UAAU,CAAC;YAE5C,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,OAAO,EAAE,QAAQ;wBACjB,SAAS,EAAE,8BAA8B,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG;qBACzE;iBACF;aACF,CAAC;QACJ,CAAC;QAED;;WAEG;QACH,gBAAgB;YACd,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACrD,CAAC;KACF,CAAC;AACJ,CAAC;AAGD;;;GAGG;AACH,KAAK,UAAU,gBAAgB,CAAC,OAAoB;IAClD,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3C,MAAM,kBAAkB,GAAuB,EAAE,CAAC;IAElD,iCAAiC;IACjC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAED,8CAA8C;IAC9C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE;QACxC,GAAG,EAAE,OAAO;QACZ,QAAQ,EAAE,KAAK;QACf,MAAM,EAAE,CAAC,iBAAiB,CAAC;KAC5B,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAEnD,sBAAsB;QACtB,MAAM,gBAAgB,GAAG,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACxE,IAAI,gBAAgB,EAAE,CAAC;YACrB,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAExC,oEAAoE;YACpE,MAAM,aAAa,GAAG,WAAW,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAChE,IAAI,aAAa,EAAE,CAAC;gBAClB,IAAI,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,2BAA2B;gBAC3B,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;gBAEpD,6CAA6C;gBAC7C,0CAA0C;gBAC1C,uEAAuE;gBACvE,IAAI,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAEpE,8DAA8D;gBAC9D,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,OAAO,EAAE,CAAC;oBACzC,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;oBACpC,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;wBACtB,SAAS,GAAG,EAAE,CAAC;oBACjB,CAAC;gBACH,CAAC;gBAED,4BAA4B;gBAC5B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC/B,SAAS,GAAG,GAAG,GAAG,SAAS,CAAC;gBAC9B,CAAC;gBAED,sCAAsC;gBACtC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;oBACnC,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;gBAClC,CAAC;gBAED,gDAAgD;gBAChD,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC;gBAEpD,8BAA8B;gBAC9B,wEAAwE;gBACxE,IAAI,aAAa,GAAG,SAAS,CAAC;gBAC9B,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;oBACpB,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBACrD,aAAa,GAAG,iBAAiB,GAAG,SAAS,CAAC;gBAChD,CAAC;gBAED,kBAAkB,CAAC,aAAa,CAAC,GAAG,UAAU,CAAC;YACjD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED,oCAAoC;AACpC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ops-ai/toggly-docusaurus-plugin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Docusaurus plugin and React bindings for Toggly feature flag gating",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./client": {
|
|
15
|
+
"types": "./dist/client/index.d.ts",
|
|
16
|
+
"import": "./dist/client/index.mjs",
|
|
17
|
+
"require": "./dist/client/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc",
|
|
25
|
+
"dev": "tsc --watch",
|
|
26
|
+
"clean": "rm -rf dist",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"lint": "eslint src --ext .ts,.tsx"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"toggly",
|
|
32
|
+
"docusaurus",
|
|
33
|
+
"feature-flags",
|
|
34
|
+
"react",
|
|
35
|
+
"documentation"
|
|
36
|
+
],
|
|
37
|
+
"author": "Toggly",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@ops-ai/toggly-client-core": "workspace:*",
|
|
41
|
+
"glob": "^10.3.10",
|
|
42
|
+
"react": "^18.3.1"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@docusaurus/core": "^3.0.0",
|
|
46
|
+
"react": "^18.0.0",
|
|
47
|
+
"react-dom": "^18.0.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@docusaurus/core": "^3.9.2",
|
|
51
|
+
"@docusaurus/types": "^3.9.2",
|
|
52
|
+
"@types/node": "^20.0.0",
|
|
53
|
+
"@types/react": "^18.2.0",
|
|
54
|
+
"@types/react-dom": "^18.2.0",
|
|
55
|
+
"@types/webpack": "^5.28.0",
|
|
56
|
+
"typescript": "^5.3.3",
|
|
57
|
+
"webpack": "^5.89.0"
|
|
58
|
+
}
|
|
59
|
+
}
|