@zenmanage/nextjs 0.0.0-stage → 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 +326 -2
- package/dist/chunk-PMTVMVXJ.js +109 -0
- package/dist/chunk-PMTVMVXJ.js.map +1 -0
- package/dist/chunk-ZUB4F2DA.js +237 -0
- package/dist/chunk-ZUB4F2DA.js.map +1 -0
- package/dist/client.cjs +287 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +38 -0
- package/dist/client.d.ts +38 -0
- package/dist/client.js +263 -0
- package/dist/client.js.map +1 -0
- package/dist/index.cjs +377 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +24 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware.cjs +199 -0
- package/dist/middleware.cjs.map +1 -0
- package/dist/middleware.d.cts +16 -0
- package/dist/middleware.d.ts +16 -0
- package/dist/middleware.js +10 -0
- package/dist/middleware.js.map +1 -0
- package/dist/server.cjs +182 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +31 -0
- package/dist/server.d.ts +31 -0
- package/dist/server.js +25 -0
- package/dist/server.js.map +1 -0
- package/dist/types-CFBzBNpk.d.cts +103 -0
- package/dist/types-CFBzBNpk.d.ts +103 -0
- package/package.json +137 -4
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
// src/server.ts
|
|
2
|
+
import {
|
|
3
|
+
ConfigBuilder,
|
|
4
|
+
DefaultsCollection as DefaultsCollection3,
|
|
5
|
+
Zenmanage
|
|
6
|
+
} from "@zenmanage/sdk";
|
|
7
|
+
|
|
8
|
+
// src/bootstrap.ts
|
|
9
|
+
import {
|
|
10
|
+
Context,
|
|
11
|
+
DefaultsCollection
|
|
12
|
+
} from "@zenmanage/sdk";
|
|
13
|
+
|
|
14
|
+
// src/types.ts
|
|
15
|
+
var DEFAULT_BOOTSTRAP_ELEMENT_ID = "__ZENMANAGE_BOOTSTRAP__";
|
|
16
|
+
var DEFAULT_SERVER_CACHE_TTL = 60;
|
|
17
|
+
|
|
18
|
+
// src/bootstrap.ts
|
|
19
|
+
var ELEMENT_ID_PATTERN = /^[A-Za-z_][\w:.-]*$/;
|
|
20
|
+
function escapeForScriptTag(value) {
|
|
21
|
+
return value.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
22
|
+
}
|
|
23
|
+
function isPlainObject(value) {
|
|
24
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
function isFlagValue(value) {
|
|
27
|
+
return typeof value === "boolean" || typeof value === "string" || typeof value === "number" && Number.isFinite(value) || typeof value === "object" && value !== null;
|
|
28
|
+
}
|
|
29
|
+
function buildBootstrapPayload(flags, options = {}) {
|
|
30
|
+
const values = Array.isArray(flags) ? Object.fromEntries(flags.map((flag) => [flag.getKey(), flag.getValue()])) : flags;
|
|
31
|
+
return {
|
|
32
|
+
version: 1,
|
|
33
|
+
generatedAt: (options.generatedAt ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
34
|
+
flags: values,
|
|
35
|
+
...options.context ? { context: options.context.toJSON() } : {}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function serializeBootstrapPayload(payload) {
|
|
39
|
+
return escapeForScriptTag(JSON.stringify(payload));
|
|
40
|
+
}
|
|
41
|
+
function deserializeBootstrapPayload(serializedPayload) {
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(serializedPayload);
|
|
44
|
+
if (!isPlainObject(parsed) || parsed.version !== 1 || !isPlainObject(parsed.flags) || typeof parsed.generatedAt !== "string") {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const flags = Object.fromEntries(
|
|
48
|
+
Object.entries(parsed.flags).filter(([, value]) => isFlagValue(value))
|
|
49
|
+
);
|
|
50
|
+
return {
|
|
51
|
+
version: 1,
|
|
52
|
+
generatedAt: parsed.generatedAt,
|
|
53
|
+
flags,
|
|
54
|
+
...isPlainObject(parsed.context) ? { context: parsed.context } : {}
|
|
55
|
+
};
|
|
56
|
+
} catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function buildBootstrapScript(payload, options = {}) {
|
|
61
|
+
const elementId = options.elementId ?? DEFAULT_BOOTSTRAP_ELEMENT_ID;
|
|
62
|
+
if (!ELEMENT_ID_PATTERN.test(elementId)) {
|
|
63
|
+
throw new Error(`Invalid bootstrap element id "${elementId}".`);
|
|
64
|
+
}
|
|
65
|
+
const serialized = serializeBootstrapPayload(payload);
|
|
66
|
+
return `<script id="${elementId}" type="application/json">${serialized}</script>`;
|
|
67
|
+
}
|
|
68
|
+
function readBootstrapPayloadFromDocument(elementId = DEFAULT_BOOTSTRAP_ELEMENT_ID) {
|
|
69
|
+
if (typeof document === "undefined") {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const element = document.getElementById(elementId);
|
|
73
|
+
if (!element) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const text = element.textContent ?? "";
|
|
77
|
+
return deserializeBootstrapPayload(text);
|
|
78
|
+
}
|
|
79
|
+
function defaultsFromBootstrapPayload(payload) {
|
|
80
|
+
if (!payload) {
|
|
81
|
+
return void 0;
|
|
82
|
+
}
|
|
83
|
+
return DefaultsCollection.fromObject(payload.flags);
|
|
84
|
+
}
|
|
85
|
+
function defaultsFromBootstrapDocument(elementId = DEFAULT_BOOTSTRAP_ELEMENT_ID) {
|
|
86
|
+
return defaultsFromBootstrapPayload(readBootstrapPayloadFromDocument(elementId));
|
|
87
|
+
}
|
|
88
|
+
function contextFromBootstrapPayload(payload) {
|
|
89
|
+
if (!payload?.context) {
|
|
90
|
+
return void 0;
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
return Context.fromObject(payload.context);
|
|
94
|
+
} catch {
|
|
95
|
+
return void 0;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// package.json
|
|
100
|
+
var version = "1.0.0";
|
|
101
|
+
|
|
102
|
+
// src/identity.ts
|
|
103
|
+
var CLIENT_AGENT = "zenmanage-nextjs";
|
|
104
|
+
var PACKAGE_VERSION = version;
|
|
105
|
+
|
|
106
|
+
// src/defaults.ts
|
|
107
|
+
import { DefaultsCollection as DefaultsCollection2 } from "@zenmanage/sdk";
|
|
108
|
+
function mergeDefaults(base, bootstrap) {
|
|
109
|
+
if (!base && !bootstrap) {
|
|
110
|
+
return void 0;
|
|
111
|
+
}
|
|
112
|
+
const merged = new DefaultsCollection2();
|
|
113
|
+
for (const source of [bootstrap, base]) {
|
|
114
|
+
if (!source) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
for (const key of source.keys()) {
|
|
118
|
+
const value = source.get(key);
|
|
119
|
+
if (value !== void 0) {
|
|
120
|
+
merged.set(key, value);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return merged;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/server.ts
|
|
128
|
+
function buildClient(options) {
|
|
129
|
+
const builder = ConfigBuilder.create().withEnvironmentToken(options.environmentToken).withClientAgent(CLIENT_AGENT).withSdkVersion(PACKAGE_VERSION).withCacheTtl(options.cacheTtl ?? DEFAULT_SERVER_CACHE_TTL);
|
|
130
|
+
if (options.apiEndpoint) {
|
|
131
|
+
builder.withApiEndpoint(options.apiEndpoint);
|
|
132
|
+
}
|
|
133
|
+
if (typeof options.enableUsageReporting === "boolean") {
|
|
134
|
+
builder.withUsageReporting(options.enableUsageReporting);
|
|
135
|
+
}
|
|
136
|
+
if (options.logger) {
|
|
137
|
+
builder.withLogger(options.logger);
|
|
138
|
+
}
|
|
139
|
+
return new Zenmanage(builder.build());
|
|
140
|
+
}
|
|
141
|
+
var clientsWithoutLogger = /* @__PURE__ */ new Map();
|
|
142
|
+
var clientsByLogger = /* @__PURE__ */ new WeakMap();
|
|
143
|
+
function configurationKey(options) {
|
|
144
|
+
return JSON.stringify([
|
|
145
|
+
options.environmentToken,
|
|
146
|
+
options.apiEndpoint ?? null,
|
|
147
|
+
options.cacheTtl ?? null,
|
|
148
|
+
options.enableUsageReporting ?? null
|
|
149
|
+
]);
|
|
150
|
+
}
|
|
151
|
+
function createServerClient(options) {
|
|
152
|
+
let clients = clientsWithoutLogger;
|
|
153
|
+
if (options.logger) {
|
|
154
|
+
clients = clientsByLogger.get(options.logger) ?? /* @__PURE__ */ new Map();
|
|
155
|
+
clientsByLogger.set(options.logger, clients);
|
|
156
|
+
}
|
|
157
|
+
const key = configurationKey(options);
|
|
158
|
+
let client = clients.get(key);
|
|
159
|
+
if (!client) {
|
|
160
|
+
client = buildClient(options);
|
|
161
|
+
clients.set(key, client);
|
|
162
|
+
}
|
|
163
|
+
return client;
|
|
164
|
+
}
|
|
165
|
+
function clearServerClients() {
|
|
166
|
+
clientsWithoutLogger.clear();
|
|
167
|
+
clientsByLogger = /* @__PURE__ */ new WeakMap();
|
|
168
|
+
}
|
|
169
|
+
function createServerRuntime(options) {
|
|
170
|
+
const client = createServerClient(options);
|
|
171
|
+
let manager = client.flags().withDefaults(options.defaults ?? new DefaultsCollection3());
|
|
172
|
+
if (options.context) {
|
|
173
|
+
manager = manager.withContext(options.context);
|
|
174
|
+
}
|
|
175
|
+
return { client, manager };
|
|
176
|
+
}
|
|
177
|
+
function createServerManager(options) {
|
|
178
|
+
return createServerRuntime(options).manager;
|
|
179
|
+
}
|
|
180
|
+
async function getServerFlag(input) {
|
|
181
|
+
const manager = createServerManager(input);
|
|
182
|
+
return manager.single(input.key, input.defaultValue);
|
|
183
|
+
}
|
|
184
|
+
async function getServerFlags(input) {
|
|
185
|
+
const manager = createServerManager(input);
|
|
186
|
+
return manager.all();
|
|
187
|
+
}
|
|
188
|
+
async function preloadServerFlags(input) {
|
|
189
|
+
const manager = createServerManager(input);
|
|
190
|
+
await manager.all();
|
|
191
|
+
return manager;
|
|
192
|
+
}
|
|
193
|
+
async function getFlagValue(input, fallback) {
|
|
194
|
+
const flag = await getServerFlag(input);
|
|
195
|
+
if (typeof fallback === "boolean") {
|
|
196
|
+
return flag.asBool();
|
|
197
|
+
}
|
|
198
|
+
if (typeof fallback === "number") {
|
|
199
|
+
return flag.asNumber();
|
|
200
|
+
}
|
|
201
|
+
if (typeof fallback === "string") {
|
|
202
|
+
return flag.asString();
|
|
203
|
+
}
|
|
204
|
+
return flag.asJson();
|
|
205
|
+
}
|
|
206
|
+
async function getBootstrapPayload(input) {
|
|
207
|
+
const flags = await getServerFlags(input);
|
|
208
|
+
const wanted = input.keys ? new Set(input.keys) : null;
|
|
209
|
+
return buildBootstrapPayload(
|
|
210
|
+
flags.filter((flag) => wanted === null || wanted.has(flag.getKey())),
|
|
211
|
+
{ context: input.includeContext ? input.context : void 0 }
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export {
|
|
216
|
+
DEFAULT_BOOTSTRAP_ELEMENT_ID,
|
|
217
|
+
DEFAULT_SERVER_CACHE_TTL,
|
|
218
|
+
buildBootstrapPayload,
|
|
219
|
+
serializeBootstrapPayload,
|
|
220
|
+
deserializeBootstrapPayload,
|
|
221
|
+
buildBootstrapScript,
|
|
222
|
+
readBootstrapPayloadFromDocument,
|
|
223
|
+
defaultsFromBootstrapPayload,
|
|
224
|
+
defaultsFromBootstrapDocument,
|
|
225
|
+
contextFromBootstrapPayload,
|
|
226
|
+
mergeDefaults,
|
|
227
|
+
createServerClient,
|
|
228
|
+
clearServerClients,
|
|
229
|
+
createServerRuntime,
|
|
230
|
+
createServerManager,
|
|
231
|
+
getServerFlag,
|
|
232
|
+
getServerFlags,
|
|
233
|
+
preloadServerFlags,
|
|
234
|
+
getFlagValue,
|
|
235
|
+
getBootstrapPayload
|
|
236
|
+
};
|
|
237
|
+
//# sourceMappingURL=chunk-ZUB4F2DA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/bootstrap.ts","../src/types.ts","../package.json","../src/identity.ts","../src/defaults.ts"],"sourcesContent":["import {\n ConfigBuilder,\n DefaultsCollection,\n Zenmanage,\n type Flag,\n type FlagManager,\n type FlagValue,\n type Logger,\n} from '@zenmanage/sdk';\nimport { buildBootstrapPayload } from './bootstrap';\nimport { CLIENT_AGENT, PACKAGE_VERSION } from './identity';\nimport {\n DEFAULT_SERVER_CACHE_TTL,\n type BootstrapPayload,\n type NextFlagsRuntime,\n type NextZenmanageClientOptions,\n type ServerBootstrapInput,\n type ServerFlagInput,\n type ServerFlagsInput,\n type WidenFlagValue,\n} from './types';\n\nexport { mergeDefaults } from './defaults';\n\nfunction buildClient(options: NextZenmanageClientOptions): Zenmanage {\n const builder = ConfigBuilder.create()\n .withEnvironmentToken(options.environmentToken)\n .withClientAgent(CLIENT_AGENT)\n .withSdkVersion(PACKAGE_VERSION)\n .withCacheTtl(options.cacheTtl ?? DEFAULT_SERVER_CACHE_TTL);\n\n if (options.apiEndpoint) {\n builder.withApiEndpoint(options.apiEndpoint);\n }\n\n if (typeof options.enableUsageReporting === 'boolean') {\n builder.withUsageReporting(options.enableUsageReporting);\n }\n\n if (options.logger) {\n builder.withLogger(options.logger);\n }\n\n return new Zenmanage(builder.build());\n}\n\n// A client owns the rules cache, so building one per call would refetch the rules for every\n// flag on every request. Clients are shared per configuration instead, for the life of the\n// server process (or edge isolate). Loggers are compared by identity, hence the WeakMap.\nconst clientsWithoutLogger = new Map<string, Zenmanage>();\nlet clientsByLogger = new WeakMap<Logger, Map<string, Zenmanage>>();\n\nfunction configurationKey(options: NextZenmanageClientOptions): string {\n return JSON.stringify([\n options.environmentToken,\n options.apiEndpoint ?? null,\n options.cacheTtl ?? null,\n options.enableUsageReporting ?? null,\n ]);\n}\n\n/**\n * Returns the client for this configuration, creating it on first use. Calls with the same\n * token, endpoint, TTL, usage setting and logger share one client and so one rules cache.\n */\nexport function createServerClient(options: NextZenmanageClientOptions): Zenmanage {\n let clients = clientsWithoutLogger;\n\n if (options.logger) {\n clients = clientsByLogger.get(options.logger) ?? new Map<string, Zenmanage>();\n clientsByLogger.set(options.logger, clients);\n }\n\n const key = configurationKey(options);\n let client = clients.get(key);\n\n if (!client) {\n client = buildClient(options);\n clients.set(key, client);\n }\n\n return client;\n}\n\n/** Forgets every shared client, and with them their cached rules. Mostly useful in tests. */\nexport function clearServerClients(): void {\n clientsWithoutLogger.clear();\n clientsByLogger = new WeakMap();\n}\n\nexport function createServerRuntime(options: ServerFlagsInput): NextFlagsRuntime {\n const client = createServerClient(options);\n\n // A manager loads its rules once and keeps them, whatever the cache TTL. Handing out the\n // client's own manager would pin the first rules it saw for the life of the process, so\n // every call gets a copy that reads the shared cache (and so honors the TTL) instead.\n let manager = client.flags().withDefaults(options.defaults ?? new DefaultsCollection());\n\n if (options.context) {\n manager = manager.withContext(options.context);\n }\n\n return { client, manager };\n}\n\nexport function createServerManager(options: ServerFlagsInput): FlagManager {\n return createServerRuntime(options).manager;\n}\n\nexport async function getServerFlag(input: ServerFlagInput): Promise<Flag> {\n const manager = createServerManager(input);\n return manager.single(input.key, input.defaultValue);\n}\n\nexport async function getServerFlags(input: ServerFlagsInput): Promise<Flag[]> {\n const manager = createServerManager(input);\n return manager.all();\n}\n\nexport async function preloadServerFlags(input: ServerFlagsInput): Promise<FlagManager> {\n const manager = createServerManager(input);\n await manager.all();\n return manager;\n}\n\n/**\n * Evaluates a flag and returns its value as the type of `fallback`: a boolean, number or\n * string, or a JSON object or array. A literal fallback (`'control'`, `false`) gives the\n * widened type (`string`, `boolean`), so the result can be compared with other values.\n */\nexport async function getFlagValue<T extends FlagValue>(\n input: ServerFlagInput,\n fallback: T\n): Promise<WidenFlagValue<T>> {\n const flag = await getServerFlag(input);\n\n if (typeof fallback === 'boolean') {\n return flag.asBool() as WidenFlagValue<T>;\n }\n\n if (typeof fallback === 'number') {\n return flag.asNumber() as WidenFlagValue<T>;\n }\n\n if (typeof fallback === 'string') {\n return flag.asString() as WidenFlagValue<T>;\n }\n\n return flag.asJson() as WidenFlagValue<T>;\n}\n\n/**\n * Evaluates flags on the server and packages them for `NextFlagsProvider`. Pass `keys` to\n * send only the flags client components read.\n */\nexport async function getBootstrapPayload(input: ServerBootstrapInput): Promise<BootstrapPayload> {\n const flags = await getServerFlags(input);\n const wanted = input.keys ? new Set(input.keys) : null;\n\n return buildBootstrapPayload(\n flags.filter((flag) => wanted === null || wanted.has(flag.getKey())),\n { context: input.includeContext ? input.context : undefined }\n );\n}\n","import {\n Context,\n DefaultsCollection,\n type ContextData,\n type Flag,\n type FlagValue,\n} from '@zenmanage/sdk';\nimport type {\n BootstrapPayload,\n BuildBootstrapPayloadOptions,\n BuildBootstrapScriptOptions,\n} from './types';\nimport { DEFAULT_BOOTSTRAP_ELEMENT_ID } from './types';\n\nconst ELEMENT_ID_PATTERN = /^[A-Za-z_][\\w:.-]*$/;\n\nfunction escapeForScriptTag(value: string): string {\n return value\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isFlagValue(value: unknown): value is FlagValue {\n return (\n typeof value === 'boolean' ||\n typeof value === 'string' ||\n (typeof value === 'number' && Number.isFinite(value)) ||\n (typeof value === 'object' && value !== null)\n );\n}\n\n/**\n * Builds the payload `NextFlagsProvider` reads. Accepts the flags straight from\n * `getServerFlags`, or a plain `{ key: value }` record.\n */\nexport function buildBootstrapPayload(\n flags: Flag[] | Record<string, FlagValue>,\n options: BuildBootstrapPayloadOptions = {}\n): BootstrapPayload {\n const values = Array.isArray(flags)\n ? Object.fromEntries(flags.map((flag) => [flag.getKey(), flag.getValue()]))\n : flags;\n\n // `context` is left out rather than set to undefined: Next.js refuses undefined in the props\n // `getServerSideProps` returns, and this payload is meant to be passed there.\n return {\n version: 1,\n generatedAt: (options.generatedAt ?? new Date()).toISOString(),\n flags: values,\n ...(options.context ? { context: options.context.toJSON() } : {}),\n };\n}\n\nexport function serializeBootstrapPayload(payload: BootstrapPayload): string {\n return escapeForScriptTag(JSON.stringify(payload));\n}\n\nexport function deserializeBootstrapPayload(serializedPayload: string): BootstrapPayload | null {\n try {\n const parsed: unknown = JSON.parse(serializedPayload);\n\n if (\n !isPlainObject(parsed) ||\n parsed.version !== 1 ||\n !isPlainObject(parsed.flags) ||\n typeof parsed.generatedAt !== 'string'\n ) {\n return null;\n }\n\n const flags = Object.fromEntries(\n Object.entries(parsed.flags).filter(([, value]) => isFlagValue(value))\n ) as Record<string, FlagValue>;\n\n return {\n version: 1,\n generatedAt: parsed.generatedAt,\n flags,\n ...(isPlainObject(parsed.context)\n ? { context: parsed.context as unknown as ContextData }\n : {}),\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Renders the payload as a JSON `<script>` tag for pages that can't pass props to the provider.\n * Prefer the `bootstrapPayload` prop: only a prop is identical on the server and in the browser.\n */\nexport function buildBootstrapScript(\n payload: BootstrapPayload,\n options: BuildBootstrapScriptOptions = {}\n): string {\n const elementId = options.elementId ?? DEFAULT_BOOTSTRAP_ELEMENT_ID;\n\n if (!ELEMENT_ID_PATTERN.test(elementId)) {\n throw new Error(`Invalid bootstrap element id \"${elementId}\".`);\n }\n\n const serialized = serializeBootstrapPayload(payload);\n return `<script id=\"${elementId}\" type=\"application/json\">${serialized}</script>`;\n}\n\nexport function readBootstrapPayloadFromDocument(\n elementId = DEFAULT_BOOTSTRAP_ELEMENT_ID\n): BootstrapPayload | null {\n if (typeof document === 'undefined') {\n return null;\n }\n\n const element = document.getElementById(elementId);\n if (!element) {\n return null;\n }\n\n const text = element.textContent ?? '';\n return deserializeBootstrapPayload(text);\n}\n\nexport function defaultsFromBootstrapPayload(\n payload: BootstrapPayload | null | undefined\n): DefaultsCollection | undefined {\n if (!payload) {\n return undefined;\n }\n\n return DefaultsCollection.fromObject(payload.flags);\n}\n\nexport function defaultsFromBootstrapDocument(\n elementId = DEFAULT_BOOTSTRAP_ELEMENT_ID\n): DefaultsCollection | undefined {\n return defaultsFromBootstrapPayload(readBootstrapPayloadFromDocument(elementId));\n}\n\nexport function contextFromBootstrapPayload(\n payload: BootstrapPayload | null | undefined\n): Context | undefined {\n if (!payload?.context) {\n return undefined;\n }\n\n try {\n return Context.fromObject(payload.context);\n } catch {\n return undefined;\n }\n}\n","import type {\n Context,\n ContextData,\n DefaultsCollection,\n FlagManager,\n FlagValue,\n Logger,\n Zenmanage,\n} from '@zenmanage/sdk';\nimport type { FlagsProviderProps } from '@zenmanage/react';\n\nexport const DEFAULT_BOOTSTRAP_ELEMENT_ID = '__ZENMANAGE_BOOTSTRAP__';\n\n/**\n * Rules are cached in memory for this many seconds. The SDK's own default is an hour, which\n * would leave a long-running `next start` server on stale rules; a minute keeps flag changes\n * visible quickly while still sharing one fetch across every request and component.\n */\nexport const DEFAULT_SERVER_CACHE_TTL = 60;\n\n/**\n * Widens a literal (`false`, `'control'`, `1500`) to its primitive type, so a value read with\n * a literal fallback is `boolean`, `string` or `number` rather than the literal. Object and\n * array values (JSON flags) pass through unchanged.\n */\nexport type WidenFlagValue<T extends FlagValue> = T extends boolean\n ? boolean\n : T extends number\n ? number\n : T extends string\n ? string\n : T;\n\nexport interface NextZenmanageClientOptions {\n /** A server key (`srv_...`). Server and edge runtimes reject client keys. */\n environmentToken: string;\n apiEndpoint?: string;\n /** Seconds to cache rules in memory. Defaults to {@link DEFAULT_SERVER_CACHE_TTL}. */\n cacheTtl?: number;\n enableUsageReporting?: boolean;\n logger?: Logger;\n}\n\nexport interface ServerFlagInput extends NextZenmanageClientOptions {\n key: string;\n defaultValue?: FlagValue;\n context?: Context;\n defaults?: DefaultsCollection;\n}\n\nexport interface ServerFlagsInput extends NextZenmanageClientOptions {\n context?: Context;\n defaults?: DefaultsCollection;\n}\n\nexport interface ServerBootstrapInput extends ServerFlagsInput {\n /**\n * The flags to send to the browser. Bootstrapping every flag puts each flag's key and\n * value in the page source, so list only what client components read.\n */\n keys?: string[];\n /** Include the evaluation context in the payload so the browser evaluates for the same user. */\n includeContext?: boolean;\n}\n\nexport interface BootstrapPayload {\n version: 1;\n generatedAt: string;\n flags: Record<string, FlagValue>;\n context?: ContextData;\n}\n\nexport interface BuildBootstrapPayloadOptions {\n context?: Context;\n generatedAt?: Date;\n}\n\nexport interface BuildBootstrapScriptOptions {\n elementId?: string;\n}\n\nexport interface RequestCookieValue {\n value: string;\n}\n\nexport interface RequestCookiesLike {\n get(name: string): RequestCookieValue | string | undefined;\n}\n\nexport interface RequestGeoLike {\n country?: string;\n region?: string;\n city?: string;\n}\n\nexport interface RequestLike {\n headers: Headers;\n cookies?: RequestCookiesLike;\n nextUrl?: { pathname: string };\n url?: string;\n /** Removed from `NextRequest` in Next.js 15; the forwarding headers are used instead. */\n ip?: string | null;\n /** Removed from `NextRequest` in Next.js 15; the Vercel and Cloudflare headers are used instead. */\n geo?: RequestGeoLike;\n}\n\nexport interface BuildRequestContextOptions {\n contextType?: string;\n contextName?: string;\n identifierCookieName?: string;\n identifierHeaderName?: string;\n /** Add `country`, `region` and `city` attributes when the platform reports them. Default `true`. */\n includeGeo?: boolean;\n /** Add the visitor's IP address as an `ip` attribute. Default `false`: an IP is personal data. */\n includeIp?: boolean;\n additionalAttributes?: Record<string, string | string[] | undefined>;\n}\n\nexport interface MiddlewareFlagInput extends NextZenmanageClientOptions {\n request: RequestLike;\n key: string;\n defaultValue?: FlagValue;\n defaults?: DefaultsCollection;\n requestContext?: BuildRequestContextOptions;\n}\n\nexport interface NextFlagsProviderProps extends Omit<FlagsProviderProps, 'defaults'> {\n defaults?: DefaultsCollection;\n /**\n * Flags evaluated on the server. Pass it as a prop so the server render and the first\n * client render see the same value, which is what keeps hydration clean.\n */\n bootstrapPayload?: BootstrapPayload | null;\n /** Read the payload from a `<script>` tag with this id when `bootstrapPayload` isn't set. */\n bootstrapElementId?: string;\n}\n\nexport interface NextFlagsRuntime {\n client: Zenmanage;\n manager: FlagManager;\n}\n","{\n \"name\": \"@zenmanage/nextjs\",\n \"version\": \"1.0.0\",\n \"description\": \"Next.js integration helpers for Zenmanage feature flags: server evaluation, middleware, and hydration-safe client bootstrap\",\n \"keywords\": [\n \"nextjs\",\n \"next.js\",\n \"react\",\n \"ssr\",\n \"app-router\",\n \"pages-router\",\n \"middleware\",\n \"feature-flags\",\n \"feature-toggles\",\n \"feature-management\",\n \"remote-config\",\n \"ab-testing\",\n \"experiments\",\n \"zenmanage\"\n ],\n \"homepage\": \"https://github.com/zenmanage/zenmanage-nextjs#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/zenmanage/zenmanage-nextjs/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/zenmanage/zenmanage-nextjs.git\"\n },\n \"license\": \"MIT\",\n \"author\": \"Zenmanage\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./server\": {\n \"import\": {\n \"types\": \"./dist/server.d.ts\",\n \"default\": \"./dist/server.js\"\n },\n \"require\": {\n \"types\": \"./dist/server.d.cts\",\n \"default\": \"./dist/server.cjs\"\n }\n },\n \"./middleware\": {\n \"import\": {\n \"types\": \"./dist/middleware.d.ts\",\n \"default\": \"./dist/middleware.js\"\n },\n \"require\": {\n \"types\": \"./dist/middleware.d.cts\",\n \"default\": \"./dist/middleware.cjs\"\n }\n },\n \"./client\": {\n \"import\": {\n \"types\": \"./dist/client.d.ts\",\n \"default\": \"./dist/client.js\"\n },\n \"require\": {\n \"types\": \"./dist/client.d.cts\",\n \"default\": \"./dist/client.cjs\"\n }\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"sideEffects\": false,\n \"scripts\": {\n \"build\": \"rm -rf dist && tsup\",\n \"clean\": \"rm -rf dist coverage\",\n \"changeset\": \"changeset\",\n \"version-packages\": \"changeset version\",\n \"release\": \"changeset publish\",\n \"lint\": \"eslint src tests --ext .ts,.tsx\",\n \"lint:fix\": \"eslint src tests --ext .ts,.tsx --fix\",\n \"format\": \"prettier --write \\\"src/**/*.{ts,tsx}\\\" \\\"tests/**/*.{ts,tsx}\\\" \\\"examples/**/*.{ts,tsx}\\\" \\\"examples/smoke-app/**/*.{js,jsx}\\\" \\\"scripts/**/*.mjs\\\" \\\"*.{md,json,yml,yaml,cjs}\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.{ts,tsx}\\\" \\\"tests/**/*.{ts,tsx}\\\" \\\"examples/**/*.{ts,tsx}\\\" \\\"examples/smoke-app/**/*.{js,jsx}\\\" \\\"scripts/**/*.mjs\\\" \\\"*.{md,json,yml,yaml,cjs}\\\"\",\n \"type-check\": \"tsc --noEmit && tsc -p tsconfig.test.json --noEmit && tsc -p tsconfig.examples.json\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"test:smoke\": \"npm run build && node scripts/smoke.mjs\",\n \"validate\": \"npm run format:check && npm run lint && npm run type-check && npm run test:coverage && npm run build && npm run test:smoke\",\n \"prepublishOnly\": \"npm run validate\"\n },\n \"peerDependencies\": {\n \"@zenmanage/react\": \"^1.0.0\",\n \"@zenmanage/sdk\": \"^3.5.0\",\n \"next\": \"^13.4.0 || ^14.0.0 || ^15.0.0 || ^16.0.0\",\n \"react\": \"^18.2.0 || ^19.0.0\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.28.1\",\n \"@testing-library/react\": \"^16.0.1\",\n \"@types/node\": \"^20.11.0\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@typescript-eslint/eslint-plugin\": \"^6.20.0\",\n \"@typescript-eslint/parser\": \"^6.20.0\",\n \"@vitest/coverage-v8\": \"^1.6.0\",\n \"@zenmanage/react\": \"^1.0.0\",\n \"@zenmanage/sdk\": \"^3.5.0\",\n \"eslint\": \"^8.57.0\",\n \"eslint-config-prettier\": \"^9.1.0\",\n \"eslint-plugin-prettier\": \"^5.2.1\",\n \"eslint-plugin-react-hooks\": \"^5.1.0\",\n \"jsdom\": \"^24.1.1\",\n \"next\": \"^15.5.0\",\n \"prettier\": \"^3.3.3\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"tsup\": \"^8.2.4\",\n \"typescript\": \"^5.6.2\",\n \"vitest\": \"^1.6.0\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"provenance\": true\n }\n}\n","import { version } from '../package.json';\n\n/** The client agent the API registers this package under (see the api's EnsureClientAgentIsValid). */\nexport const CLIENT_AGENT = 'zenmanage-nextjs';\n\nexport const PACKAGE_VERSION: string = version;\n","import { DefaultsCollection } from '@zenmanage/sdk';\n\n/** Combines two collections. `base` wins where both define a key. */\nexport function mergeDefaults(\n base?: DefaultsCollection,\n bootstrap?: DefaultsCollection\n): DefaultsCollection | undefined {\n if (!base && !bootstrap) {\n return undefined;\n }\n\n const merged = new DefaultsCollection();\n\n for (const source of [bootstrap, base]) {\n if (!source) {\n continue;\n }\n\n for (const key of source.keys()) {\n const value = source.get(key);\n if (value !== undefined) {\n merged.set(key, value);\n }\n }\n }\n\n return merged;\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA,sBAAAA;AAAA,EACA;AAAA,OAKK;;;ACRP;AAAA,EACE;AAAA,EACA;AAAA,OAIK;;;ACKA,IAAM,+BAA+B;AAOrC,IAAM,2BAA2B;;;ADJxC,IAAM,qBAAqB;AAE3B,SAAS,mBAAmB,OAAuB;AACjD,SAAO,MACJ,QAAQ,MAAM,SAAS,EACvB,QAAQ,MAAM,SAAS,EACvB,QAAQ,MAAM,SAAS,EACvB,QAAQ,WAAW,SAAS,EAC5B,QAAQ,WAAW,SAAS;AACjC;AAEA,SAAS,cAAc,OAAkD;AACvE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,YAAY,OAAoC;AACvD,SACE,OAAO,UAAU,aACjB,OAAO,UAAU,YAChB,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAClD,OAAO,UAAU,YAAY,UAAU;AAE5C;AAMO,SAAS,sBACd,OACA,UAAwC,CAAC,GACvB;AAClB,QAAM,SAAS,MAAM,QAAQ,KAAK,IAC9B,OAAO,YAAY,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IACxE;AAIJ,SAAO;AAAA,IACL,SAAS;AAAA,IACT,cAAc,QAAQ,eAAe,oBAAI,KAAK,GAAG,YAAY;AAAA,IAC7D,OAAO;AAAA,IACP,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,OAAO,EAAE,IAAI,CAAC;AAAA,EACjE;AACF;AAEO,SAAS,0BAA0B,SAAmC;AAC3E,SAAO,mBAAmB,KAAK,UAAU,OAAO,CAAC;AACnD;AAEO,SAAS,4BAA4B,mBAAoD;AAC9F,MAAI;AACF,UAAM,SAAkB,KAAK,MAAM,iBAAiB;AAEpD,QACE,CAAC,cAAc,MAAM,KACrB,OAAO,YAAY,KACnB,CAAC,cAAc,OAAO,KAAK,KAC3B,OAAO,OAAO,gBAAgB,UAC9B;AACA,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,OAAO;AAAA,MACnB,OAAO,QAAQ,OAAO,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,YAAY,KAAK,CAAC;AAAA,IACvE;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa,OAAO;AAAA,MACpB;AAAA,MACA,GAAI,cAAc,OAAO,OAAO,IAC5B,EAAE,SAAS,OAAO,QAAkC,IACpD,CAAC;AAAA,IACP;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,qBACd,SACA,UAAuC,CAAC,GAChC;AACR,QAAM,YAAY,QAAQ,aAAa;AAEvC,MAAI,CAAC,mBAAmB,KAAK,SAAS,GAAG;AACvC,UAAM,IAAI,MAAM,iCAAiC,SAAS,IAAI;AAAA,EAChE;AAEA,QAAM,aAAa,0BAA0B,OAAO;AACpD,SAAO,eAAe,SAAS,6BAA6B,UAAU;AACxE;AAEO,SAAS,iCACd,YAAY,8BACa;AACzB,MAAI,OAAO,aAAa,aAAa;AACnC,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,SAAS,eAAe,SAAS;AACjD,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,QAAQ,eAAe;AACpC,SAAO,4BAA4B,IAAI;AACzC;AAEO,SAAS,6BACd,SACgC;AAChC,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,SAAO,mBAAmB,WAAW,QAAQ,KAAK;AACpD;AAEO,SAAS,8BACd,YAAY,8BACoB;AAChC,SAAO,6BAA6B,iCAAiC,SAAS,CAAC;AACjF;AAEO,SAAS,4BACd,SACqB;AACrB,MAAI,CAAC,SAAS,SAAS;AACrB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,WAAO,QAAQ,WAAW,QAAQ,OAAO;AAAA,EAC3C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AE1JE,cAAW;;;ACCN,IAAM,eAAe;AAErB,IAAM,kBAA0B;;;ACLvC,SAAS,sBAAAC,2BAA0B;AAG5B,SAAS,cACd,MACA,WACgC;AAChC,MAAI,CAAC,QAAQ,CAAC,WAAW;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,IAAIA,oBAAmB;AAEtC,aAAW,UAAU,CAAC,WAAW,IAAI,GAAG;AACtC,QAAI,CAAC,QAAQ;AACX;AAAA,IACF;AAEA,eAAW,OAAO,OAAO,KAAK,GAAG;AAC/B,YAAM,QAAQ,OAAO,IAAI,GAAG;AAC5B,UAAI,UAAU,QAAW;AACvB,eAAO,IAAI,KAAK,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ALHA,SAAS,YAAY,SAAgD;AACnE,QAAM,UAAU,cAAc,OAAO,EAClC,qBAAqB,QAAQ,gBAAgB,EAC7C,gBAAgB,YAAY,EAC5B,eAAe,eAAe,EAC9B,aAAa,QAAQ,YAAY,wBAAwB;AAE5D,MAAI,QAAQ,aAAa;AACvB,YAAQ,gBAAgB,QAAQ,WAAW;AAAA,EAC7C;AAEA,MAAI,OAAO,QAAQ,yBAAyB,WAAW;AACrD,YAAQ,mBAAmB,QAAQ,oBAAoB;AAAA,EACzD;AAEA,MAAI,QAAQ,QAAQ;AAClB,YAAQ,WAAW,QAAQ,MAAM;AAAA,EACnC;AAEA,SAAO,IAAI,UAAU,QAAQ,MAAM,CAAC;AACtC;AAKA,IAAM,uBAAuB,oBAAI,IAAuB;AACxD,IAAI,kBAAkB,oBAAI,QAAwC;AAElE,SAAS,iBAAiB,SAA6C;AACrE,SAAO,KAAK,UAAU;AAAA,IACpB,QAAQ;AAAA,IACR,QAAQ,eAAe;AAAA,IACvB,QAAQ,YAAY;AAAA,IACpB,QAAQ,wBAAwB;AAAA,EAClC,CAAC;AACH;AAMO,SAAS,mBAAmB,SAAgD;AACjF,MAAI,UAAU;AAEd,MAAI,QAAQ,QAAQ;AAClB,cAAU,gBAAgB,IAAI,QAAQ,MAAM,KAAK,oBAAI,IAAuB;AAC5E,oBAAgB,IAAI,QAAQ,QAAQ,OAAO;AAAA,EAC7C;AAEA,QAAM,MAAM,iBAAiB,OAAO;AACpC,MAAI,SAAS,QAAQ,IAAI,GAAG;AAE5B,MAAI,CAAC,QAAQ;AACX,aAAS,YAAY,OAAO;AAC5B,YAAQ,IAAI,KAAK,MAAM;AAAA,EACzB;AAEA,SAAO;AACT;AAGO,SAAS,qBAA2B;AACzC,uBAAqB,MAAM;AAC3B,oBAAkB,oBAAI,QAAQ;AAChC;AAEO,SAAS,oBAAoB,SAA6C;AAC/E,QAAM,SAAS,mBAAmB,OAAO;AAKzC,MAAI,UAAU,OAAO,MAAM,EAAE,aAAa,QAAQ,YAAY,IAAIC,oBAAmB,CAAC;AAEtF,MAAI,QAAQ,SAAS;AACnB,cAAU,QAAQ,YAAY,QAAQ,OAAO;AAAA,EAC/C;AAEA,SAAO,EAAE,QAAQ,QAAQ;AAC3B;AAEO,SAAS,oBAAoB,SAAwC;AAC1E,SAAO,oBAAoB,OAAO,EAAE;AACtC;AAEA,eAAsB,cAAc,OAAuC;AACzE,QAAM,UAAU,oBAAoB,KAAK;AACzC,SAAO,QAAQ,OAAO,MAAM,KAAK,MAAM,YAAY;AACrD;AAEA,eAAsB,eAAe,OAA0C;AAC7E,QAAM,UAAU,oBAAoB,KAAK;AACzC,SAAO,QAAQ,IAAI;AACrB;AAEA,eAAsB,mBAAmB,OAA+C;AACtF,QAAM,UAAU,oBAAoB,KAAK;AACzC,QAAM,QAAQ,IAAI;AAClB,SAAO;AACT;AAOA,eAAsB,aACpB,OACA,UAC4B;AAC5B,QAAM,OAAO,MAAM,cAAc,KAAK;AAEtC,MAAI,OAAO,aAAa,WAAW;AACjC,WAAO,KAAK,OAAO;AAAA,EACrB;AAEA,MAAI,OAAO,aAAa,UAAU;AAChC,WAAO,KAAK,SAAS;AAAA,EACvB;AAEA,MAAI,OAAO,aAAa,UAAU;AAChC,WAAO,KAAK,SAAS;AAAA,EACvB;AAEA,SAAO,KAAK,OAAO;AACrB;AAMA,eAAsB,oBAAoB,OAAwD;AAChG,QAAM,QAAQ,MAAM,eAAe,KAAK;AACxC,QAAM,SAAS,MAAM,OAAO,IAAI,IAAI,MAAM,IAAI,IAAI;AAElD,SAAO;AAAA,IACL,MAAM,OAAO,CAAC,SAAS,WAAW,QAAQ,OAAO,IAAI,KAAK,OAAO,CAAC,CAAC;AAAA,IACnE,EAAE,SAAS,MAAM,iBAAiB,MAAM,UAAU,OAAU;AAAA,EAC9D;AACF;","names":["DefaultsCollection","DefaultsCollection","DefaultsCollection"]}
|
package/dist/client.cjs
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/client.ts
|
|
22
|
+
var client_exports = {};
|
|
23
|
+
__export(client_exports, {
|
|
24
|
+
NextFlagsProvider: () => NextFlagsProvider,
|
|
25
|
+
useFlag: () => useFlag,
|
|
26
|
+
useFlagsContext: () => import_react8.useFlagsContext,
|
|
27
|
+
useVariant: () => useVariant
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(client_exports);
|
|
30
|
+
|
|
31
|
+
// src/client/NextFlagsProvider.tsx
|
|
32
|
+
var import_react4 = require("react");
|
|
33
|
+
var import_react5 = require("@zenmanage/react");
|
|
34
|
+
|
|
35
|
+
// src/bootstrap.ts
|
|
36
|
+
var import_sdk = require("@zenmanage/sdk");
|
|
37
|
+
|
|
38
|
+
// src/types.ts
|
|
39
|
+
var DEFAULT_BOOTSTRAP_ELEMENT_ID = "__ZENMANAGE_BOOTSTRAP__";
|
|
40
|
+
|
|
41
|
+
// src/bootstrap.ts
|
|
42
|
+
function isPlainObject(value) {
|
|
43
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44
|
+
}
|
|
45
|
+
function isFlagValue(value) {
|
|
46
|
+
return typeof value === "boolean" || typeof value === "string" || typeof value === "number" && Number.isFinite(value) || typeof value === "object" && value !== null;
|
|
47
|
+
}
|
|
48
|
+
function deserializeBootstrapPayload(serializedPayload) {
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(serializedPayload);
|
|
51
|
+
if (!isPlainObject(parsed) || parsed.version !== 1 || !isPlainObject(parsed.flags) || typeof parsed.generatedAt !== "string") {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const flags = Object.fromEntries(
|
|
55
|
+
Object.entries(parsed.flags).filter(([, value]) => isFlagValue(value))
|
|
56
|
+
);
|
|
57
|
+
return {
|
|
58
|
+
version: 1,
|
|
59
|
+
generatedAt: parsed.generatedAt,
|
|
60
|
+
flags,
|
|
61
|
+
...isPlainObject(parsed.context) ? { context: parsed.context } : {}
|
|
62
|
+
};
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function defaultsFromBootstrapPayload(payload) {
|
|
68
|
+
if (!payload) {
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
return import_sdk.DefaultsCollection.fromObject(payload.flags);
|
|
72
|
+
}
|
|
73
|
+
function contextFromBootstrapPayload(payload) {
|
|
74
|
+
if (!payload?.context) {
|
|
75
|
+
return void 0;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
return import_sdk.Context.fromObject(payload.context);
|
|
79
|
+
} catch {
|
|
80
|
+
return void 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/defaults.ts
|
|
85
|
+
var import_sdk2 = require("@zenmanage/sdk");
|
|
86
|
+
function mergeDefaults(base, bootstrap) {
|
|
87
|
+
if (!base && !bootstrap) {
|
|
88
|
+
return void 0;
|
|
89
|
+
}
|
|
90
|
+
const merged = new import_sdk2.DefaultsCollection();
|
|
91
|
+
for (const source of [bootstrap, base]) {
|
|
92
|
+
if (!source) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
for (const key of source.keys()) {
|
|
96
|
+
const value = source.get(key);
|
|
97
|
+
if (value !== void 0) {
|
|
98
|
+
merged.set(key, value);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return merged;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// src/client/BootstrapProvider.tsx
|
|
106
|
+
var import_react2 = require("react");
|
|
107
|
+
var import_react3 = require("@zenmanage/react");
|
|
108
|
+
|
|
109
|
+
// src/client/context.ts
|
|
110
|
+
var import_react = require("react");
|
|
111
|
+
var BootstrapContext = (0, import_react.createContext)(null);
|
|
112
|
+
|
|
113
|
+
// src/client/BootstrapProvider.tsx
|
|
114
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
115
|
+
function BootstrapProvider({ flags, children }) {
|
|
116
|
+
const { manager, isReady, revision } = (0, import_react3.useFlagsContext)();
|
|
117
|
+
const [live, setLive] = (0, import_react2.useState)(null);
|
|
118
|
+
(0, import_react2.useEffect)(() => {
|
|
119
|
+
if (!flags || !isReady) {
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
let isCurrent = true;
|
|
123
|
+
manager.all().then(
|
|
124
|
+
(loaded) => isCurrent && setLive(new Set(loaded.map((flag) => flag.getKey()))),
|
|
125
|
+
() => isCurrent && setLive(/* @__PURE__ */ new Set())
|
|
126
|
+
);
|
|
127
|
+
return () => {
|
|
128
|
+
isCurrent = false;
|
|
129
|
+
};
|
|
130
|
+
}, [flags, isReady, manager, revision]);
|
|
131
|
+
const value = (0, import_react2.useMemo)(() => flags ? { flags, live } : null, [flags, live]);
|
|
132
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BootstrapContext.Provider, { value, children });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/client/createClient.ts
|
|
136
|
+
var import_sdk3 = require("@zenmanage/sdk");
|
|
137
|
+
|
|
138
|
+
// package.json
|
|
139
|
+
var version = "1.0.0";
|
|
140
|
+
|
|
141
|
+
// src/identity.ts
|
|
142
|
+
var CLIENT_AGENT = "zenmanage-nextjs";
|
|
143
|
+
var PACKAGE_VERSION = version;
|
|
144
|
+
|
|
145
|
+
// src/client/createClient.ts
|
|
146
|
+
function isServerRender() {
|
|
147
|
+
return typeof window === "undefined" && typeof document === "undefined";
|
|
148
|
+
}
|
|
149
|
+
function createProviderClient(options) {
|
|
150
|
+
const { environmentToken, apiEndpoint, cacheTtl, enableUsageReporting } = options;
|
|
151
|
+
if (!environmentToken) {
|
|
152
|
+
throw new Error("NextFlagsProvider requires either a client or an environmentToken.");
|
|
153
|
+
}
|
|
154
|
+
if (environmentToken.startsWith("srv_")) {
|
|
155
|
+
throw new Error(
|
|
156
|
+
"NextFlagsProvider received a server key (srv_...). Server keys must never reach the browser; use a client key (cli_...)."
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
if (isServerRender()) {
|
|
160
|
+
if (!environmentToken.startsWith("cli_")) {
|
|
161
|
+
throw new Error("NextFlagsProvider needs a client key (cli_...).");
|
|
162
|
+
}
|
|
163
|
+
return new import_sdk3.Zenmanage({
|
|
164
|
+
environmentToken,
|
|
165
|
+
apiEndpoint,
|
|
166
|
+
cacheTtl,
|
|
167
|
+
enableUsageReporting,
|
|
168
|
+
clientAgent: CLIENT_AGENT,
|
|
169
|
+
sdkVersion: PACKAGE_VERSION
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
const builder = import_sdk3.ConfigBuilder.create().withEnvironmentToken(environmentToken).withClientAgent(CLIENT_AGENT).withSdkVersion(PACKAGE_VERSION);
|
|
173
|
+
if (apiEndpoint) {
|
|
174
|
+
builder.withApiEndpoint(apiEndpoint);
|
|
175
|
+
}
|
|
176
|
+
if (typeof cacheTtl === "number") {
|
|
177
|
+
builder.withCacheTtl(cacheTtl);
|
|
178
|
+
}
|
|
179
|
+
if (typeof enableUsageReporting === "boolean") {
|
|
180
|
+
builder.withUsageReporting(enableUsageReporting);
|
|
181
|
+
}
|
|
182
|
+
return new import_sdk3.Zenmanage(builder.build());
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// src/client/NextFlagsProvider.tsx
|
|
186
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
187
|
+
var subscribeToNothing = () => () => void 0;
|
|
188
|
+
function useDocumentPayload(elementId, enabled) {
|
|
189
|
+
const cache = (0, import_react4.useRef)({
|
|
190
|
+
text: null,
|
|
191
|
+
payload: null
|
|
192
|
+
});
|
|
193
|
+
const getSnapshot = (0, import_react4.useCallback)(() => {
|
|
194
|
+
if (!enabled || typeof document === "undefined") {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
const text = document.getElementById(elementId)?.textContent ?? null;
|
|
198
|
+
if (text !== cache.current.text) {
|
|
199
|
+
cache.current = { text, payload: text === null ? null : deserializeBootstrapPayload(text) };
|
|
200
|
+
}
|
|
201
|
+
return cache.current.payload;
|
|
202
|
+
}, [elementId, enabled]);
|
|
203
|
+
return (0, import_react4.useSyncExternalStore)(subscribeToNothing, getSnapshot, () => null);
|
|
204
|
+
}
|
|
205
|
+
function NextFlagsProvider({
|
|
206
|
+
client,
|
|
207
|
+
environmentToken,
|
|
208
|
+
apiEndpoint,
|
|
209
|
+
cacheTtl,
|
|
210
|
+
enableUsageReporting,
|
|
211
|
+
context,
|
|
212
|
+
defaults,
|
|
213
|
+
bootstrapPayload,
|
|
214
|
+
bootstrapElementId = DEFAULT_BOOTSTRAP_ELEMENT_ID,
|
|
215
|
+
children,
|
|
216
|
+
...providerProps
|
|
217
|
+
}) {
|
|
218
|
+
const documentPayload = useDocumentPayload(bootstrapElementId, !bootstrapPayload);
|
|
219
|
+
const payload = bootstrapPayload ?? documentPayload;
|
|
220
|
+
const resolvedClient = (0, import_react4.useMemo)(
|
|
221
|
+
() => client ?? createProviderClient({ environmentToken, apiEndpoint, cacheTtl, enableUsageReporting }),
|
|
222
|
+
[client, environmentToken, apiEndpoint, cacheTtl, enableUsageReporting]
|
|
223
|
+
);
|
|
224
|
+
const mergedDefaults = (0, import_react4.useMemo)(
|
|
225
|
+
() => mergeDefaults(defaults, defaultsFromBootstrapPayload(payload)),
|
|
226
|
+
[defaults, payload]
|
|
227
|
+
);
|
|
228
|
+
const resolvedContext = (0, import_react4.useMemo)(
|
|
229
|
+
() => context ?? contextFromBootstrapPayload(payload),
|
|
230
|
+
[context, payload]
|
|
231
|
+
);
|
|
232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
233
|
+
import_react5.FlagsProvider,
|
|
234
|
+
{
|
|
235
|
+
...providerProps,
|
|
236
|
+
client: resolvedClient,
|
|
237
|
+
context: resolvedContext,
|
|
238
|
+
defaults: mergedDefaults,
|
|
239
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BootstrapProvider, { flags: payload?.flags ?? null, children })
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/client/hooks.ts
|
|
245
|
+
var import_react6 = require("react");
|
|
246
|
+
var import_react7 = require("@zenmanage/react");
|
|
247
|
+
function sameKind(candidate, fallback) {
|
|
248
|
+
if (typeof fallback === "object") {
|
|
249
|
+
return typeof candidate === "object" && candidate !== null && Array.isArray(candidate) === Array.isArray(fallback);
|
|
250
|
+
}
|
|
251
|
+
return typeof candidate === typeof fallback;
|
|
252
|
+
}
|
|
253
|
+
function useFlag(key, defaultValue) {
|
|
254
|
+
const bootstrap = (0, import_react6.useContext)(BootstrapContext);
|
|
255
|
+
const result = (0, import_react7.useFlag)(key, defaultValue);
|
|
256
|
+
const seed = bootstrap?.flags[key];
|
|
257
|
+
if (seed === void 0 || !sameKind(seed, defaultValue)) {
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
const hasLiveValue = bootstrap?.live?.has(key) === true;
|
|
261
|
+
if (hasLiveValue && !result.isLoading) {
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
return { ...result, value: seed, isLoading: false };
|
|
265
|
+
}
|
|
266
|
+
function useVariant(key, defaultVariant = "control") {
|
|
267
|
+
const result = useFlag(key, defaultVariant);
|
|
268
|
+
return {
|
|
269
|
+
key,
|
|
270
|
+
variant: result.value,
|
|
271
|
+
flag: result.flag,
|
|
272
|
+
isLoading: result.isLoading,
|
|
273
|
+
error: result.error,
|
|
274
|
+
refresh: result.refresh
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// src/client.ts
|
|
279
|
+
var import_react8 = require("@zenmanage/react");
|
|
280
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
281
|
+
0 && (module.exports = {
|
|
282
|
+
NextFlagsProvider,
|
|
283
|
+
useFlag,
|
|
284
|
+
useFlagsContext,
|
|
285
|
+
useVariant
|
|
286
|
+
});
|
|
287
|
+
//# sourceMappingURL=client.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/client/NextFlagsProvider.tsx","../src/bootstrap.ts","../src/types.ts","../src/defaults.ts","../src/client/BootstrapProvider.tsx","../src/client/context.ts","../src/client/createClient.ts","../package.json","../src/identity.ts","../src/client/hooks.ts"],"sourcesContent":["export { NextFlagsProvider } from './client/NextFlagsProvider';\nexport { useFlag, useVariant } from './client/hooks';\nexport { useFlagsContext } from '@zenmanage/react';\nexport type { NextFlagsProviderProps } from './types';\n","import { useCallback, useMemo, useRef, useSyncExternalStore, type ReactElement } from 'react';\nimport { FlagsProvider } from '@zenmanage/react';\nimport {\n contextFromBootstrapPayload,\n defaultsFromBootstrapPayload,\n deserializeBootstrapPayload,\n} from '../bootstrap';\nimport { mergeDefaults } from '../defaults';\nimport {\n DEFAULT_BOOTSTRAP_ELEMENT_ID,\n type BootstrapPayload,\n type NextFlagsProviderProps,\n} from '../types';\nimport { BootstrapProvider } from './BootstrapProvider';\nimport { createProviderClient } from './createClient';\n\nconst subscribeToNothing = (): (() => void) => () => undefined;\n\n/**\n * Reads the payload from a `<script>` tag. `useSyncExternalStore` serves `null` while\n * hydrating and the real payload right after, so the first client render matches the server\n * render instead of reading the DOM mid-render.\n */\nfunction useDocumentPayload(elementId: string, enabled: boolean): BootstrapPayload | null {\n const cache = useRef<{ text: string | null; payload: BootstrapPayload | null }>({\n text: null,\n payload: null,\n });\n\n const getSnapshot = useCallback((): BootstrapPayload | null => {\n if (!enabled || typeof document === 'undefined') {\n return null;\n }\n\n const text = document.getElementById(elementId)?.textContent ?? null;\n if (text !== cache.current.text) {\n cache.current = { text, payload: text === null ? null : deserializeBootstrapPayload(text) };\n }\n\n return cache.current.payload;\n }, [elementId, enabled]);\n\n return useSyncExternalStore(subscribeToNothing, getSnapshot, () => null);\n}\n\nexport function NextFlagsProvider({\n client,\n environmentToken,\n apiEndpoint,\n cacheTtl,\n enableUsageReporting,\n context,\n defaults,\n bootstrapPayload,\n bootstrapElementId = DEFAULT_BOOTSTRAP_ELEMENT_ID,\n children,\n ...providerProps\n}: NextFlagsProviderProps): ReactElement {\n const documentPayload = useDocumentPayload(bootstrapElementId, !bootstrapPayload);\n const payload = bootstrapPayload ?? documentPayload;\n\n const resolvedClient = useMemo(\n () =>\n client ??\n createProviderClient({ environmentToken, apiEndpoint, cacheTtl, enableUsageReporting }),\n [client, environmentToken, apiEndpoint, cacheTtl, enableUsageReporting]\n );\n\n const mergedDefaults = useMemo(\n () => mergeDefaults(defaults, defaultsFromBootstrapPayload(payload)),\n [defaults, payload]\n );\n\n // Without an explicit context the browser evaluates for the user the server evaluated for.\n const resolvedContext = useMemo(\n () => context ?? contextFromBootstrapPayload(payload),\n [context, payload]\n );\n\n return (\n <FlagsProvider\n {...providerProps}\n client={resolvedClient}\n context={resolvedContext}\n defaults={mergedDefaults}\n >\n <BootstrapProvider flags={payload?.flags ?? null}>{children}</BootstrapProvider>\n </FlagsProvider>\n );\n}\n","import {\n Context,\n DefaultsCollection,\n type ContextData,\n type Flag,\n type FlagValue,\n} from '@zenmanage/sdk';\nimport type {\n BootstrapPayload,\n BuildBootstrapPayloadOptions,\n BuildBootstrapScriptOptions,\n} from './types';\nimport { DEFAULT_BOOTSTRAP_ELEMENT_ID } from './types';\n\nconst ELEMENT_ID_PATTERN = /^[A-Za-z_][\\w:.-]*$/;\n\nfunction escapeForScriptTag(value: string): string {\n return value\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isFlagValue(value: unknown): value is FlagValue {\n return (\n typeof value === 'boolean' ||\n typeof value === 'string' ||\n (typeof value === 'number' && Number.isFinite(value)) ||\n (typeof value === 'object' && value !== null)\n );\n}\n\n/**\n * Builds the payload `NextFlagsProvider` reads. Accepts the flags straight from\n * `getServerFlags`, or a plain `{ key: value }` record.\n */\nexport function buildBootstrapPayload(\n flags: Flag[] | Record<string, FlagValue>,\n options: BuildBootstrapPayloadOptions = {}\n): BootstrapPayload {\n const values = Array.isArray(flags)\n ? Object.fromEntries(flags.map((flag) => [flag.getKey(), flag.getValue()]))\n : flags;\n\n // `context` is left out rather than set to undefined: Next.js refuses undefined in the props\n // `getServerSideProps` returns, and this payload is meant to be passed there.\n return {\n version: 1,\n generatedAt: (options.generatedAt ?? new Date()).toISOString(),\n flags: values,\n ...(options.context ? { context: options.context.toJSON() } : {}),\n };\n}\n\nexport function serializeBootstrapPayload(payload: BootstrapPayload): string {\n return escapeForScriptTag(JSON.stringify(payload));\n}\n\nexport function deserializeBootstrapPayload(serializedPayload: string): BootstrapPayload | null {\n try {\n const parsed: unknown = JSON.parse(serializedPayload);\n\n if (\n !isPlainObject(parsed) ||\n parsed.version !== 1 ||\n !isPlainObject(parsed.flags) ||\n typeof parsed.generatedAt !== 'string'\n ) {\n return null;\n }\n\n const flags = Object.fromEntries(\n Object.entries(parsed.flags).filter(([, value]) => isFlagValue(value))\n ) as Record<string, FlagValue>;\n\n return {\n version: 1,\n generatedAt: parsed.generatedAt,\n flags,\n ...(isPlainObject(parsed.context)\n ? { context: parsed.context as unknown as ContextData }\n : {}),\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Renders the payload as a JSON `<script>` tag for pages that can't pass props to the provider.\n * Prefer the `bootstrapPayload` prop: only a prop is identical on the server and in the browser.\n */\nexport function buildBootstrapScript(\n payload: BootstrapPayload,\n options: BuildBootstrapScriptOptions = {}\n): string {\n const elementId = options.elementId ?? DEFAULT_BOOTSTRAP_ELEMENT_ID;\n\n if (!ELEMENT_ID_PATTERN.test(elementId)) {\n throw new Error(`Invalid bootstrap element id \"${elementId}\".`);\n }\n\n const serialized = serializeBootstrapPayload(payload);\n return `<script id=\"${elementId}\" type=\"application/json\">${serialized}</script>`;\n}\n\nexport function readBootstrapPayloadFromDocument(\n elementId = DEFAULT_BOOTSTRAP_ELEMENT_ID\n): BootstrapPayload | null {\n if (typeof document === 'undefined') {\n return null;\n }\n\n const element = document.getElementById(elementId);\n if (!element) {\n return null;\n }\n\n const text = element.textContent ?? '';\n return deserializeBootstrapPayload(text);\n}\n\nexport function defaultsFromBootstrapPayload(\n payload: BootstrapPayload | null | undefined\n): DefaultsCollection | undefined {\n if (!payload) {\n return undefined;\n }\n\n return DefaultsCollection.fromObject(payload.flags);\n}\n\nexport function defaultsFromBootstrapDocument(\n elementId = DEFAULT_BOOTSTRAP_ELEMENT_ID\n): DefaultsCollection | undefined {\n return defaultsFromBootstrapPayload(readBootstrapPayloadFromDocument(elementId));\n}\n\nexport function contextFromBootstrapPayload(\n payload: BootstrapPayload | null | undefined\n): Context | undefined {\n if (!payload?.context) {\n return undefined;\n }\n\n try {\n return Context.fromObject(payload.context);\n } catch {\n return undefined;\n }\n}\n","import type {\n Context,\n ContextData,\n DefaultsCollection,\n FlagManager,\n FlagValue,\n Logger,\n Zenmanage,\n} from '@zenmanage/sdk';\nimport type { FlagsProviderProps } from '@zenmanage/react';\n\nexport const DEFAULT_BOOTSTRAP_ELEMENT_ID = '__ZENMANAGE_BOOTSTRAP__';\n\n/**\n * Rules are cached in memory for this many seconds. The SDK's own default is an hour, which\n * would leave a long-running `next start` server on stale rules; a minute keeps flag changes\n * visible quickly while still sharing one fetch across every request and component.\n */\nexport const DEFAULT_SERVER_CACHE_TTL = 60;\n\n/**\n * Widens a literal (`false`, `'control'`, `1500`) to its primitive type, so a value read with\n * a literal fallback is `boolean`, `string` or `number` rather than the literal. Object and\n * array values (JSON flags) pass through unchanged.\n */\nexport type WidenFlagValue<T extends FlagValue> = T extends boolean\n ? boolean\n : T extends number\n ? number\n : T extends string\n ? string\n : T;\n\nexport interface NextZenmanageClientOptions {\n /** A server key (`srv_...`). Server and edge runtimes reject client keys. */\n environmentToken: string;\n apiEndpoint?: string;\n /** Seconds to cache rules in memory. Defaults to {@link DEFAULT_SERVER_CACHE_TTL}. */\n cacheTtl?: number;\n enableUsageReporting?: boolean;\n logger?: Logger;\n}\n\nexport interface ServerFlagInput extends NextZenmanageClientOptions {\n key: string;\n defaultValue?: FlagValue;\n context?: Context;\n defaults?: DefaultsCollection;\n}\n\nexport interface ServerFlagsInput extends NextZenmanageClientOptions {\n context?: Context;\n defaults?: DefaultsCollection;\n}\n\nexport interface ServerBootstrapInput extends ServerFlagsInput {\n /**\n * The flags to send to the browser. Bootstrapping every flag puts each flag's key and\n * value in the page source, so list only what client components read.\n */\n keys?: string[];\n /** Include the evaluation context in the payload so the browser evaluates for the same user. */\n includeContext?: boolean;\n}\n\nexport interface BootstrapPayload {\n version: 1;\n generatedAt: string;\n flags: Record<string, FlagValue>;\n context?: ContextData;\n}\n\nexport interface BuildBootstrapPayloadOptions {\n context?: Context;\n generatedAt?: Date;\n}\n\nexport interface BuildBootstrapScriptOptions {\n elementId?: string;\n}\n\nexport interface RequestCookieValue {\n value: string;\n}\n\nexport interface RequestCookiesLike {\n get(name: string): RequestCookieValue | string | undefined;\n}\n\nexport interface RequestGeoLike {\n country?: string;\n region?: string;\n city?: string;\n}\n\nexport interface RequestLike {\n headers: Headers;\n cookies?: RequestCookiesLike;\n nextUrl?: { pathname: string };\n url?: string;\n /** Removed from `NextRequest` in Next.js 15; the forwarding headers are used instead. */\n ip?: string | null;\n /** Removed from `NextRequest` in Next.js 15; the Vercel and Cloudflare headers are used instead. */\n geo?: RequestGeoLike;\n}\n\nexport interface BuildRequestContextOptions {\n contextType?: string;\n contextName?: string;\n identifierCookieName?: string;\n identifierHeaderName?: string;\n /** Add `country`, `region` and `city` attributes when the platform reports them. Default `true`. */\n includeGeo?: boolean;\n /** Add the visitor's IP address as an `ip` attribute. Default `false`: an IP is personal data. */\n includeIp?: boolean;\n additionalAttributes?: Record<string, string | string[] | undefined>;\n}\n\nexport interface MiddlewareFlagInput extends NextZenmanageClientOptions {\n request: RequestLike;\n key: string;\n defaultValue?: FlagValue;\n defaults?: DefaultsCollection;\n requestContext?: BuildRequestContextOptions;\n}\n\nexport interface NextFlagsProviderProps extends Omit<FlagsProviderProps, 'defaults'> {\n defaults?: DefaultsCollection;\n /**\n * Flags evaluated on the server. Pass it as a prop so the server render and the first\n * client render see the same value, which is what keeps hydration clean.\n */\n bootstrapPayload?: BootstrapPayload | null;\n /** Read the payload from a `<script>` tag with this id when `bootstrapPayload` isn't set. */\n bootstrapElementId?: string;\n}\n\nexport interface NextFlagsRuntime {\n client: Zenmanage;\n manager: FlagManager;\n}\n","import { DefaultsCollection } from '@zenmanage/sdk';\n\n/** Combines two collections. `base` wins where both define a key. */\nexport function mergeDefaults(\n base?: DefaultsCollection,\n bootstrap?: DefaultsCollection\n): DefaultsCollection | undefined {\n if (!base && !bootstrap) {\n return undefined;\n }\n\n const merged = new DefaultsCollection();\n\n for (const source of [bootstrap, base]) {\n if (!source) {\n continue;\n }\n\n for (const key of source.keys()) {\n const value = source.get(key);\n if (value !== undefined) {\n merged.set(key, value);\n }\n }\n }\n\n return merged;\n}\n","import { useEffect, useMemo, useState, type ReactElement, type ReactNode } from 'react';\nimport type { FlagValue } from '@zenmanage/sdk';\nimport { useFlagsContext } from '@zenmanage/react';\nimport { BootstrapContext } from './context';\n\ninterface BootstrapProviderProps {\n flags: Record<string, FlagValue> | null;\n children: ReactNode;\n}\n\n/**\n * Sits inside `FlagsProvider`. Once the browser has tried to load the rules it records which\n * flags they contain, so `useFlag` can tell \"the live value\" from \"the SDK fell back to the\n * default because nothing loaded\".\n */\nexport function BootstrapProvider({ flags, children }: BootstrapProviderProps): ReactElement {\n const { manager, isReady, revision } = useFlagsContext();\n const [live, setLive] = useState<ReadonlySet<string> | null>(null);\n\n useEffect(() => {\n if (!flags || !isReady) {\n return undefined;\n }\n\n let isCurrent = true;\n\n // The SDK serves defaults instead of throwing when rules can't be loaded, so an empty list\n // is what an unreachable API looks like.\n manager.all().then(\n (loaded) => isCurrent && setLive(new Set(loaded.map((flag) => flag.getKey()))),\n () => isCurrent && setLive(new Set())\n );\n\n return () => {\n isCurrent = false;\n };\n }, [flags, isReady, manager, revision]);\n\n const value = useMemo(() => (flags ? { flags, live } : null), [flags, live]);\n\n return <BootstrapContext.Provider value={value}>{children}</BootstrapContext.Provider>;\n}\n","import { createContext } from 'react';\nimport type { FlagValue } from '@zenmanage/sdk';\n\nexport interface BootstrapState {\n /** The flag values the server evaluated. */\n flags: Record<string, FlagValue>;\n /**\n * The keys the browser's own rules contain, or `null` until it has asked. A flag that is\n * bootstrapped but absent here has no live evaluation behind it (the rules didn't load, or\n * the flag doesn't exist), so the server's value is the best answer there is.\n */\n live: ReadonlySet<string> | null;\n}\n\n/** `null` when the provider wasn't given a bootstrap payload. */\nexport const BootstrapContext = createContext<BootstrapState | null>(null);\n","import { ConfigBuilder, Zenmanage } from '@zenmanage/sdk';\nimport { CLIENT_AGENT, PACKAGE_VERSION } from '../identity';\n\ninterface ClientOptions {\n environmentToken?: string;\n apiEndpoint?: string;\n cacheTtl?: number;\n enableUsageReporting?: boolean;\n}\n\n// Mirrors how @zenmanage/sdk tells the runtimes apart.\nfunction isServerRender(): boolean {\n return typeof window === 'undefined' && typeof document === 'undefined';\n}\n\n/**\n * Builds the client a provider hands to its hooks.\n *\n * Next.js renders Client Components on the server as well as in the browser, and the SDK\n * refuses a client key in Node.js. Nothing is fetched while rendering (effects don't run), so\n * the server render gets a client assembled without that check, which is only ever asked for\n * its defaults. The browser gets a fully validated one.\n */\nexport function createProviderClient(options: ClientOptions): Zenmanage {\n const { environmentToken, apiEndpoint, cacheTtl, enableUsageReporting } = options;\n\n if (!environmentToken) {\n throw new Error('NextFlagsProvider requires either a client or an environmentToken.');\n }\n\n // A prop on a Client Component is written into the page, so a server key here would leak.\n if (environmentToken.startsWith('srv_')) {\n throw new Error(\n 'NextFlagsProvider received a server key (srv_...). Server keys must never reach the browser; use a client key (cli_...).'\n );\n }\n\n if (isServerRender()) {\n if (!environmentToken.startsWith('cli_')) {\n throw new Error('NextFlagsProvider needs a client key (cli_...).');\n }\n\n return new Zenmanage({\n environmentToken,\n apiEndpoint,\n cacheTtl,\n enableUsageReporting,\n clientAgent: CLIENT_AGENT,\n sdkVersion: PACKAGE_VERSION,\n });\n }\n\n const builder = ConfigBuilder.create()\n .withEnvironmentToken(environmentToken)\n .withClientAgent(CLIENT_AGENT)\n .withSdkVersion(PACKAGE_VERSION);\n\n if (apiEndpoint) {\n builder.withApiEndpoint(apiEndpoint);\n }\n\n if (typeof cacheTtl === 'number') {\n builder.withCacheTtl(cacheTtl);\n }\n\n if (typeof enableUsageReporting === 'boolean') {\n builder.withUsageReporting(enableUsageReporting);\n }\n\n return new Zenmanage(builder.build());\n}\n","{\n \"name\": \"@zenmanage/nextjs\",\n \"version\": \"1.0.0\",\n \"description\": \"Next.js integration helpers for Zenmanage feature flags: server evaluation, middleware, and hydration-safe client bootstrap\",\n \"keywords\": [\n \"nextjs\",\n \"next.js\",\n \"react\",\n \"ssr\",\n \"app-router\",\n \"pages-router\",\n \"middleware\",\n \"feature-flags\",\n \"feature-toggles\",\n \"feature-management\",\n \"remote-config\",\n \"ab-testing\",\n \"experiments\",\n \"zenmanage\"\n ],\n \"homepage\": \"https://github.com/zenmanage/zenmanage-nextjs#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/zenmanage/zenmanage-nextjs/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/zenmanage/zenmanage-nextjs.git\"\n },\n \"license\": \"MIT\",\n \"author\": \"Zenmanage\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./server\": {\n \"import\": {\n \"types\": \"./dist/server.d.ts\",\n \"default\": \"./dist/server.js\"\n },\n \"require\": {\n \"types\": \"./dist/server.d.cts\",\n \"default\": \"./dist/server.cjs\"\n }\n },\n \"./middleware\": {\n \"import\": {\n \"types\": \"./dist/middleware.d.ts\",\n \"default\": \"./dist/middleware.js\"\n },\n \"require\": {\n \"types\": \"./dist/middleware.d.cts\",\n \"default\": \"./dist/middleware.cjs\"\n }\n },\n \"./client\": {\n \"import\": {\n \"types\": \"./dist/client.d.ts\",\n \"default\": \"./dist/client.js\"\n },\n \"require\": {\n \"types\": \"./dist/client.d.cts\",\n \"default\": \"./dist/client.cjs\"\n }\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"sideEffects\": false,\n \"scripts\": {\n \"build\": \"rm -rf dist && tsup\",\n \"clean\": \"rm -rf dist coverage\",\n \"changeset\": \"changeset\",\n \"version-packages\": \"changeset version\",\n \"release\": \"changeset publish\",\n \"lint\": \"eslint src tests --ext .ts,.tsx\",\n \"lint:fix\": \"eslint src tests --ext .ts,.tsx --fix\",\n \"format\": \"prettier --write \\\"src/**/*.{ts,tsx}\\\" \\\"tests/**/*.{ts,tsx}\\\" \\\"examples/**/*.{ts,tsx}\\\" \\\"examples/smoke-app/**/*.{js,jsx}\\\" \\\"scripts/**/*.mjs\\\" \\\"*.{md,json,yml,yaml,cjs}\\\"\",\n \"format:check\": \"prettier --check \\\"src/**/*.{ts,tsx}\\\" \\\"tests/**/*.{ts,tsx}\\\" \\\"examples/**/*.{ts,tsx}\\\" \\\"examples/smoke-app/**/*.{js,jsx}\\\" \\\"scripts/**/*.mjs\\\" \\\"*.{md,json,yml,yaml,cjs}\\\"\",\n \"type-check\": \"tsc --noEmit && tsc -p tsconfig.test.json --noEmit && tsc -p tsconfig.examples.json\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"test:smoke\": \"npm run build && node scripts/smoke.mjs\",\n \"validate\": \"npm run format:check && npm run lint && npm run type-check && npm run test:coverage && npm run build && npm run test:smoke\",\n \"prepublishOnly\": \"npm run validate\"\n },\n \"peerDependencies\": {\n \"@zenmanage/react\": \"^1.0.0\",\n \"@zenmanage/sdk\": \"^3.5.0\",\n \"next\": \"^13.4.0 || ^14.0.0 || ^15.0.0 || ^16.0.0\",\n \"react\": \"^18.2.0 || ^19.0.0\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.28.1\",\n \"@testing-library/react\": \"^16.0.1\",\n \"@types/node\": \"^20.11.0\",\n \"@types/react\": \"^19.2.0\",\n \"@types/react-dom\": \"^19.2.0\",\n \"@typescript-eslint/eslint-plugin\": \"^6.20.0\",\n \"@typescript-eslint/parser\": \"^6.20.0\",\n \"@vitest/coverage-v8\": \"^1.6.0\",\n \"@zenmanage/react\": \"^1.0.0\",\n \"@zenmanage/sdk\": \"^3.5.0\",\n \"eslint\": \"^8.57.0\",\n \"eslint-config-prettier\": \"^9.1.0\",\n \"eslint-plugin-prettier\": \"^5.2.1\",\n \"eslint-plugin-react-hooks\": \"^5.1.0\",\n \"jsdom\": \"^24.1.1\",\n \"next\": \"^15.5.0\",\n \"prettier\": \"^3.3.3\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"tsup\": \"^8.2.4\",\n \"typescript\": \"^5.6.2\",\n \"vitest\": \"^1.6.0\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"provenance\": true\n }\n}\n","import { version } from '../package.json';\n\n/** The client agent the API registers this package under (see the api's EnsureClientAgentIsValid). */\nexport const CLIENT_AGENT = 'zenmanage-nextjs';\n\nexport const PACKAGE_VERSION: string = version;\n","import { useContext } from 'react';\nimport type { FlagValue } from '@zenmanage/sdk';\nimport {\n useFlag as useReactFlag,\n type UseFlagResult,\n type UseVariantResult,\n type WidenFlagValue,\n} from '@zenmanage/react';\nimport { BootstrapContext } from './context';\n\nfunction sameKind(candidate: FlagValue, fallback: FlagValue): boolean {\n if (typeof fallback === 'object') {\n return (\n typeof candidate === 'object' &&\n candidate !== null &&\n Array.isArray(candidate) === Array.isArray(fallback)\n );\n }\n\n return typeof candidate === typeof fallback;\n}\n\n/**\n * Like `useFlag` from `@zenmanage/react`, but it serves the value the server evaluated until\n * the browser has a live evaluation to replace it. Both the server render and the first client\n * render use that value, with `isLoading` false, so the page hydrates without a mismatch or a\n * flash of the default. Once the browser's rules load, the live value takes over. If they\n * never load (a blocked CDN, no network), the server's value stays rather than the page\n * switching to the code default.\n *\n * Without a bootstrap value for the key it behaves exactly like the React hook.\n */\nexport function useFlag<T extends FlagValue>(\n key: string,\n defaultValue: T\n): UseFlagResult<WidenFlagValue<T>> {\n const bootstrap = useContext(BootstrapContext);\n // The hook's own default stays the fallback for the live evaluation: reporting the server's\n // value as the code default would corrupt the default-value usage the API records.\n const result = useReactFlag(key, defaultValue);\n\n const seed = bootstrap?.flags[key];\n if (seed === undefined || !sameKind(seed, defaultValue)) {\n return result;\n }\n\n const hasLiveValue = bootstrap?.live?.has(key) === true;\n if (hasLiveValue && !result.isLoading) {\n return result;\n }\n\n return { ...result, value: seed as WidenFlagValue<T>, isLoading: false };\n}\n\nexport function useVariant(key: string, defaultVariant = 'control'): UseVariantResult {\n const result = useFlag<string>(key, defaultVariant);\n\n return {\n key,\n variant: result.value,\n flag: result.flag,\n isLoading: result.isLoading,\n error: result.error,\n refresh: result.refresh,\n };\n}\n"],"mappings":"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","names":["import_react","import_sdk","import_react","import_sdk","import_jsx_runtime","import_react","useReactFlag","import_react"]}
|