@vard-app/sdk 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/fetch-store.ts","../src/client.ts","../src/schema.ts"],"sourcesContent":["// Public entrypoint for @vard/sdk\nexport { createVard } from \"./client\";\nexport { createVardFetchStore } from \"./fetch-store\";\nexport { v } from \"./schema\";\nexport type { VardSchema, InferSchema, VardSchemaFragment, MergeSchema } from \"./schema\";\nexport type {\n VardClient,\n VardOptions,\n VardStore,\n VardVariableDefinition,\n VardVariableType,\n VardVariableOptions,\n VardListItemSchema,\n InferListItem,\n VardRole,\n} from \"./types\";\n","import type { VardStore } from \"./types\";\n\nexport interface VardFetchStoreOptions {\n /**\n * Base URL of the Vard API. Defaults to https://api.vard.app\n */\n apiBase?: string;\n\n /**\n * API Key for authentication. Defaults to process.env.VARD_API_KEY.\n */\n apiKey?: string;\n\n /**\n * Custom fetch options (headers, etc.)\n */\n fetchOptions?: RequestInit;\n}\n\n/**\n * Creates a universal VardStore that fetches variable values from the Vard API.\n * Works in any environment with a global `fetch` (Browsers, Node 18+, Bun, Deno).\n */\nexport function createVardFetchStore(\n options: VardFetchStoreOptions = {}\n): VardStore & { prefetch(): Promise<void> } {\n const {\n apiBase = options.apiBase ??\n process.env.VARD_API_BASE ??\n process.env.NEXT_PUBLIC_VARD_API_BASE ??\n \"https://dash.vard.app\",\n apiKey = options.apiKey ?? process.env.VARD_API_KEY,\n fetchOptions = {},\n } = options;\n\n let resolvedValues: Map<string, unknown> | null = null;\n let structuredContent: any = null;\n let fetchPromise: Promise<{ variables: Map<string, unknown>; structured: any }> | null = null;\n\n async function fetchValues(): Promise<{ variables: Map<string, unknown>; structured: any }> {\n const isDevelopment = process.env.NODE_ENV === \"development\";\n\n if (!apiKey) {\n if (!isDevelopment) {\n console.error(\n \"\\x1b[31m[vard] Missing configuration! VARD_API_KEY is not set.\\x1b[0m\\n\" +\n \"Please set this environment variable in your production environment.\"\n );\n } else {\n console.warn(\n \"[vard] No API Key found. Running in local fallback mode (using default values).\"\n );\n }\n return { variables: new Map(), structured: {} };\n }\n\n const url = `${apiBase}/api/content/variables?structured=true`;\n\n try {\n const res = await fetch(url, {\n ...fetchOptions,\n headers: {\n ...fetchOptions.headers,\n \"X-Vard-API-Key\": apiKey,\n },\n });\n\n if (!res.ok) {\n console.warn(`[vard] Failed to fetch variables: ${res.status}`);\n return { variables: new Map(), structured: {} };\n }\n\n const data = (await res.json()) as any;\n\n // Handle both legacy (array) and new (object with structured) responses\n if (Array.isArray(data)) {\n return {\n variables: new Map(data.map((v: any) => [v.key, v.value])),\n structured: {},\n };\n }\n\n return {\n variables: new Map(data.variables.map((v: any) => [v.key, v.value])),\n structured: data.structured || {},\n };\n } catch (err) {\n return { variables: new Map(), structured: {} };\n }\n }\n\n return {\n get(key: string): unknown {\n return resolvedValues?.get(key);\n },\n\n getStructured(): any {\n return structuredContent;\n },\n\n async prefetch(): Promise<void> {\n if (resolvedValues) return;\n if (!fetchPromise) {\n fetchPromise = fetchValues();\n }\n const result = await fetchPromise;\n resolvedValues = result.variables;\n structuredContent = result.structured;\n },\n };\n}\n","import {\n VardClient,\n VardOptions,\n VardStore,\n VardVariableDefinition,\n VardVariableOptions,\n VardListItemSchema,\n InferListItem,\n VardRole,\n VardVariableType,\n} from \"./types\";\nimport {\n VardSchema,\n InferSchema,\n VardField,\n VardCollection,\n VardSchemaFragment,\n MergeSchema,\n} from \"./schema\";\nimport { createVardFetchStore } from \"./fetch-store\";\n\n// ─────────────────────────────────────────────\n// No-op store (used in local dev when no apiKey is set)\n// ─────────────────────────────────────────────\n\nlet hasLoggedNoop = false;\nconst noopStore: VardStore = {\n get: () => {\n if (!hasLoggedNoop && process.env.NODE_ENV !== \"test\") {\n console.warn(\n \"[vard] Using default values for all variables because no Store was provided to createVard().\"\n );\n hasLoggedNoop = true;\n }\n return undefined;\n },\n};\n\n// ─────────────────────────────────────────────\n// createVard — the main SDK factory\n// ─────────────────────────────────────────────\n\n/**\n * Creates a Vard client instance. Call this once at the top of your site\n * (e.g. in `lib/vard.ts`) and export the result.\n */\nexport function createVard<S extends VardSchema = any>(\n options: VardOptions<S> = {}\n): VardClient<S> {\n const store: VardStore =\n options.store ?? (options.apiKey ? createVardFetchStore(options) : noopStore);\n\n // Registry of all declared variables — used by CLI + build pipeline\n const registry: VardVariableDefinition[] = [];\n\n function register<T>(def: VardVariableDefinition<T>): T {\n if (!registry.find((d) => d.key === def.key)) {\n registry.push(def as VardVariableDefinition);\n }\n\n const stored = store.get(def.key);\n if (stored !== undefined && stored !== null) {\n return stored as T;\n }\n\n return def.defaultValue;\n }\n\n // ─────────────────────────────────────────────\n // Schema Traversal\n // ─────────────────────────────────────────────\n\n function flattenSchema(schema: VardSchema, prefix = \"\"): any {\n const result: any = {};\n\n for (const [key, value] of Object.entries(schema)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === \"object\" && value !== null && \"type\" in value) {\n // It's a field or collection\n const field = value as VardField | VardCollection;\n\n if (field.type === \"collection\") {\n // Flatten collection schema but keep it as a 'list' type for the registry\n const collection = field as VardCollection;\n const listItemSchema: Record<string, string> = {};\n for (const [fKey, fVal] of Object.entries(collection.schema)) {\n listItemSchema[fKey] = (fVal as VardField).type;\n }\n\n register({\n key: fullKey,\n label: labelFromKey(key),\n type: \"list\",\n defaultValue: [],\n editableBy: \"member\",\n listItemSchema: listItemSchema as VardListItemSchema,\n isCollection: true,\n });\n\n // In the returned object, this remains a placeholder or is proxied to the store\n Object.defineProperty(result, key, {\n get: () => store.get(fullKey) ?? [],\n enumerable: true,\n });\n } else {\n // It's a plain field\n const vardField = field as VardField;\n register({\n key: fullKey,\n label: vardField.label ?? labelFromKey(key),\n description: vardField.description,\n type: vardField.type,\n defaultValue: vardField.default,\n editableBy: vardField.editableBy ?? \"member\",\n group: vardField.group,\n });\n\n Object.defineProperty(result, key, {\n get: () => store.get(fullKey) ?? vardField.default,\n enumerable: true,\n });\n }\n } else if (typeof value === \"object\" && value !== null) {\n // It's a nested object\n result[key] = flattenSchema(value as VardSchema, fullKey);\n }\n }\n\n return result;\n }\n\n // Auto-sync schema in development\n if (options.schema && process.env.NODE_ENV === \"development\" && options.apiKey) {\n flattenSchema(options.schema);\n const definitions = [...registry];\n const apiBase =\n process.env.VARD_API_BASE ?? process.env.NEXT_PUBLIC_VARD_API_BASE ?? \"https://dash.vard.app\";\n\n fetch(`${apiBase}/api/content/variables/sync`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Vard-API-Key\": options.apiKey,\n },\n body: JSON.stringify({\n definitions,\n schema: options.schema,\n }),\n }).catch((err) => console.warn(\"[vard] Auto-sync failed:\", err));\n }\n\n const client: VardClient<S> = {\n define<NS extends VardSchema>(schema: NS): InferSchema<NS> {\n return flattenSchema(schema) as InferSchema<NS>;\n },\n\n async get(): Promise<InferSchema<S>> {\n if (store.prefetch) {\n await store.prefetch();\n }\n if (store.getStructured) {\n const structured = store.getStructured();\n if (structured && Object.keys(structured).length > 0) {\n return structured as InferSchema<S>;\n }\n }\n return flattenSchema(options.schema ?? {}) as InferSchema<S>;\n },\n\n string(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"string\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n richtext(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"richtext\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n color(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"color\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n image(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"image\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n boolean(key, fallback, opts: VardVariableOptions = {}) {\n return register<boolean>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"boolean\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n group: opts.group,\n });\n },\n\n list<LS extends VardListItemSchema>(\n key: string,\n schema: LS,\n fallback: InferListItem<LS>[],\n opts: VardVariableOptions = {}\n ): InferListItem<LS>[] {\n return register<InferListItem<LS>[]>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"list\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n listItemSchema: schema,\n group: opts.group,\n });\n },\n\n collection<LS extends VardListItemSchema>(\n key: string,\n schema: LS,\n fallback: InferListItem<LS>[],\n opts: Omit<VardVariableOptions, \"type\"> = {}\n ): InferListItem<LS>[] {\n return register<InferListItem<LS>[]>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"list\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n listItemSchema: schema,\n group: opts.group,\n isCollection: true,\n });\n },\n\n global: {\n string(key, fallback, opts = {}) {\n return client.string(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n richtext(key, fallback, opts = {}) {\n return client.richtext(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n color(key, fallback, opts = {}) {\n return client.color(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n image(key, fallback, opts = {}) {\n return client.image(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n boolean(key, fallback, opts = {}) {\n return client.boolean(key, fallback, { ...opts, group: \"Global\" } as Omit<\n VardVariableOptions,\n \"type\"\n >);\n },\n list(key, schema, fallback, opts = {}) {\n return client.list(key, schema, fallback, { ...opts, group: \"Global\" } as Omit<\n VardVariableOptions,\n \"type\"\n >);\n },\n },\n\n extend<E extends VardSchema>(fragment: VardSchemaFragment<E>): VardClient<MergeSchema<S, E>> {\n // Merge the base schema with the fragment — the fragment keys win on collision\n const mergedSchema = { ...(options.schema ?? {}), ...fragment } as unknown as MergeSchema<\n S,\n E\n >;\n // Return a new client with the merged schema, sharing the same store & registry.\n // We pass the in-memory store directly so there is no second fetch.\n return createVard<MergeSchema<S, E>>({\n ...options,\n schema: mergedSchema,\n store,\n });\n },\n\n getDefinitions() {\n return [...registry];\n },\n store,\n };\n\n return client;\n}\n\n// ─────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────\n\nfunction labelFromKey(key: string): string {\n const lastSegment = key.split(\".\").pop() ?? key;\n return lastSegment\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (c) => c.toUpperCase())\n .trim();\n}\n","import { VardVariableType, VardRole } from \"./types\";\n\nexport interface VardFieldOptions<T = any> {\n label?: string;\n description?: string;\n editableBy?: VardRole;\n group?: string;\n default?: T;\n}\n\nexport interface VardField<T = any> extends VardFieldOptions<T> {\n type: VardVariableType;\n}\n\nexport interface VardCollection<S extends Record<string, VardField | any> = any> {\n type: \"collection\";\n schema: S;\n}\n\nexport type VardSchemaValue = VardField | VardCollection | { [key: string]: VardSchemaValue };\n\nexport type VardSchema = Record<string, VardSchemaValue>;\n\n/**\n * A branded schema fragment created with `v.schema()`. Use with `vard.extend()`\n * to compose schemas defined across multiple files.\n */\nexport type VardSchemaFragment<S extends VardSchema> = S & {\n readonly __fragment: true;\n};\n\n/**\n * Merges two VardSchema types, with B's keys overriding A on collision.\n */\nexport type MergeSchema<A extends VardSchema, B extends VardSchema> = Omit<A, keyof B> & B;\n\n// ─────────────────────────────────────────────\n// The `v` helper object for schema definition\n// ─────────────────────────────────────────────\n\nexport const v = {\n string: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"string\",\n default: defaultValue,\n ...opts,\n }),\n\n richtext: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"richtext\",\n default: defaultValue,\n ...opts,\n }),\n\n color: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"color\",\n default: defaultValue,\n ...opts,\n }),\n\n image: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"image\",\n default: defaultValue,\n ...opts,\n }),\n\n boolean: (\n defaultValue?: boolean,\n opts: Omit<VardFieldOptions<boolean>, \"default\"> = {}\n ): VardField<boolean> => ({\n type: \"boolean\",\n default: defaultValue,\n ...opts,\n }),\n\n collection: <S extends Record<string, VardField | any>>(schema: S): VardCollection<S> => ({\n type: \"collection\",\n schema,\n }),\n\n /**\n * Creates a reusable schema fragment that can be merged into a Vard client\n * via `vard.extend(fragment)`. Co-locate this with your page/component.\n *\n * @example\n * // app/therapists/schema.ts\n * export const therapistSchema = v.schema({\n * therapists: v.collection({ name: v.string(), photo: v.image() }),\n * });\n *\n * // app/therapists/page.tsx\n * const { therapists } = await vard.extend(therapistSchema).get();\n */\n schema: <S extends VardSchema>(schema: S): VardSchemaFragment<S> =>\n schema as VardSchemaFragment<S>,\n};\n\n// ─────────────────────────────────────────────\n// Type inference for schema objects\n// ─────────────────────────────────────────────\n\nexport type InferSchema<T> = {\n [K in keyof T]: T[K] extends VardField<infer U>\n ? U\n : T[K] extends VardCollection<infer S>\n ? InferSchema<S>[]\n : T[K] extends object\n ? InferSchema<T[K]>\n : never;\n};\n"],"mappings":"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","names":["v"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/fetch-store.ts","../src/client.ts","../src/schema.ts"],"sourcesContent":["// Public entrypoint for @vard/sdk\nexport { createVard } from \"./client\";\nexport { createVardFetchStore } from \"./fetch-store\";\nexport { v } from \"./schema\";\nexport type { VardSchema, InferSchema, VardSchemaFragment, MergeSchema } from \"./schema\";\nexport type {\n VardClient,\n VardOptions,\n VardStore,\n VardVariableDefinition,\n VardVariableType,\n VardVariableOptions,\n VardListItemSchema,\n InferListItem,\n VardRole,\n} from \"./types\";\n","import type { VardStore } from \"./types\";\n\nexport interface VardFetchStoreOptions {\n /**\n * Base URL of the Vard API. Defaults to https://api.vard.app\n */\n apiBase?: string;\n\n /**\n * API Key for authentication. Defaults to process.env.VARD_API_KEY.\n */\n apiKey?: string;\n\n /**\n * Custom fetch options (headers, etc.)\n */\n fetchOptions?: RequestInit;\n\n /**\n * Enable verbose logging for requests and responses.\n */\n debug?: boolean;\n}\n\n/**\n * Creates a universal VardStore that fetches variable values from the Vard API.\n * Works in any environment with a global `fetch` (Browsers, Node 18+, Bun, Deno).\n */\nexport function createVardFetchStore(\n options: VardFetchStoreOptions = {}\n): VardStore & { prefetch(): Promise<void> } {\n const {\n apiBase = options.apiBase ??\n process.env.VARD_API_HOST ??\n \"https://dash.vard.app\",\n apiKey = options.apiKey ?? process.env.VARD_API_KEY,\n fetchOptions = {},\n debug = options.debug ?? false,\n } = options;\n\n let resolvedValues: Map<string, unknown> | null = null;\n let structuredContent: any = null;\n let fetchPromise: Promise<{ variables: Map<string, unknown>; structured: any }> | null = null;\n\n async function fetchValues(): Promise<{ variables: Map<string, unknown>; structured: any }> {\n const isDevelopment = process.env.NODE_ENV === \"development\";\n\n if (!apiKey) {\n if (!isDevelopment) {\n console.error(\n \"\\x1b[31m[vard] Missing configuration! VARD_API_KEY is not set.\\x1b[0m\\n\" +\n \"Please set this environment variable in your production environment.\"\n );\n } else {\n console.warn(\n \"[vard] No API Key found. Running in local fallback mode (using default values).\"\n );\n }\n return { variables: new Map(), structured: {} };\n }\n\n const url = `${apiBase}/api/content/variables`;\n\n if (debug) {\n console.log(`[vard] Request: GET ${url}`);\n console.log(`[vard] Headers:`, {\n \"X-Vard-API-Key\": apiKey.substring(0, 10) + \"...\",\n ...fetchOptions.headers,\n });\n }\n\n try {\n const res = await fetch(url, {\n ...fetchOptions,\n headers: {\n ...fetchOptions.headers,\n \"X-Vard-API-Key\": apiKey,\n },\n });\n\n if (!res.ok) {\n const errorMsg = `[vard] Failed to fetch variables from ${url} (Status: ${res.status} ${res.statusText})`;\n console.error(`\\x1b[31m${errorMsg}\\x1b[0m`);\n return { variables: new Map(), structured: {} };\n }\n\n const data = (await res.json()) as Record<string, unknown>;\n\n if (debug) {\n console.log(`[vard] Response (${res.status}):`, data);\n }\n\n // Flatten the nested structure into the internal Map for key-based lookups\n const variablesMap = new Map<string, unknown>();\n flattenObject(data, \"\", variablesMap);\n\n return {\n variables: variablesMap,\n structured: data,\n };\n } catch (err) {\n const errorMsg = `[vard] Network error fetching variables from ${url}`;\n console.error(`\\x1b[31m${errorMsg}\\x1b[0m`, err);\n return { variables: new Map(), structured: {} };\n }\n }\n\n function flattenObject(obj: any, prefix: string, map: Map<string, unknown>) {\n if (typeof obj !== \"object\" || obj === null) return;\n\n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n // If it's an array, we treat it as a single value (e.g. a collection)\n if (Array.isArray(value)) {\n map.set(fullKey, value);\n } else if (typeof value === \"object\" && value !== null) {\n flattenObject(value, fullKey, map);\n } else {\n map.set(fullKey, value);\n }\n }\n }\n\n return {\n get(key: string): unknown {\n return resolvedValues?.get(key);\n },\n\n getStructured(): any {\n return structuredContent;\n },\n\n async prefetch(): Promise<void> {\n if (resolvedValues) return;\n if (!fetchPromise) {\n fetchPromise = fetchValues();\n }\n const result = await fetchPromise;\n resolvedValues = result.variables;\n structuredContent = result.structured;\n },\n };\n}\n","import {\n VardClient,\n VardOptions,\n VardStore,\n VardVariableDefinition,\n VardVariableOptions,\n VardListItemSchema,\n InferListItem,\n VardRole,\n VardVariableType,\n} from \"./types\";\nimport {\n VardSchema,\n InferSchema,\n VardField,\n VardCollection,\n VardSchemaFragment,\n MergeSchema,\n} from \"./schema\";\nimport { createVardFetchStore } from \"./fetch-store\";\n\n// ─────────────────────────────────────────────\n// No-op store (used in local dev when no apiKey is set)\n// ─────────────────────────────────────────────\n\nlet hasLoggedNoop = false;\nconst noopStore: VardStore = {\n get: () => {\n if (!hasLoggedNoop && process.env.NODE_ENV !== \"test\") {\n console.warn(\n \"[vard] Using default values for all variables because no Store was provided to createVard().\"\n );\n hasLoggedNoop = true;\n }\n return undefined;\n },\n};\n\n// ─────────────────────────────────────────────\n// createVard — the main SDK factory\n// ─────────────────────────────────────────────\n\n/**\n * Creates a Vard client instance. Call this once at the top of your site\n * (e.g. in `lib/vard.ts`) and export the result.\n */\nexport function createVard<S extends VardSchema = any>(\n options: VardOptions<S> = {}\n): VardClient<S> {\n const store: VardStore =\n options.store ?? (options.apiKey ? createVardFetchStore(options) : noopStore);\n\n // Registry of all declared variables — used by CLI + build pipeline\n const registry: VardVariableDefinition[] = [];\n\n function register<T>(def: VardVariableDefinition<T>): T {\n if (!registry.find((d) => d.key === def.key)) {\n registry.push(def as VardVariableDefinition);\n }\n\n const stored = store.get(def.key);\n if (stored !== undefined && stored !== null) {\n return stored as T;\n }\n\n return def.defaultValue;\n }\n\n // ─────────────────────────────────────────────\n // Schema Traversal\n // ─────────────────────────────────────────────\n\n function flattenSchema(schema: VardSchema, prefix = \"\"): any {\n const result: any = {};\n\n for (const [key, value] of Object.entries(schema)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === \"object\" && value !== null && \"type\" in value) {\n // It's a field or collection\n const field = value as VardField | VardCollection;\n\n if (field.type === \"collection\") {\n // Flatten collection schema but keep it as a 'list' type for the registry\n const collection = field as VardCollection;\n const listItemSchema: Record<string, string> = {};\n for (const [fKey, fVal] of Object.entries(collection.schema)) {\n listItemSchema[fKey] = (fVal as VardField).type;\n }\n\n register({\n key: fullKey,\n label: labelFromKey(key),\n type: \"list\",\n defaultValue: [],\n editableBy: \"member\",\n listItemSchema: listItemSchema as VardListItemSchema,\n isCollection: true,\n });\n\n // In the returned object, this remains a placeholder or is proxied to the store\n Object.defineProperty(result, key, {\n get: () => store.get(fullKey) ?? [],\n enumerable: true,\n });\n } else {\n // It's a plain field\n const vardField = field as VardField;\n register({\n key: fullKey,\n label: vardField.label ?? labelFromKey(key),\n description: vardField.description,\n type: vardField.type,\n defaultValue: vardField.default,\n editableBy: vardField.editableBy ?? \"member\",\n group: vardField.group,\n });\n\n Object.defineProperty(result, key, {\n get: () => store.get(fullKey) ?? vardField.default,\n enumerable: true,\n });\n }\n } else if (typeof value === \"object\" && value !== null) {\n // It's a nested object\n result[key] = flattenSchema(value as VardSchema, fullKey);\n }\n }\n\n return result;\n }\n\n // Auto-sync schema in development\n if (options.schema && process.env.NODE_ENV === \"development\" && options.apiKey) {\n flattenSchema(options.schema);\n const definitions = [...registry];\n const apiBase = process.env.VARD_API_HOST ?? \"https://dash.vard.app\";\n\n fetch(`${apiBase}/api/content/variables/sync`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Vard-API-Key\": options.apiKey,\n },\n body: JSON.stringify({\n definitions,\n schema: options.schema,\n }),\n }).catch((err) => console.warn(\"[vard] Auto-sync failed:\", err));\n }\n\n const client: VardClient<S> = {\n define<NS extends VardSchema>(schema: NS): InferSchema<NS> {\n return flattenSchema(schema) as InferSchema<NS>;\n },\n\n async get(): Promise<InferSchema<S>> {\n if (store.prefetch) {\n await store.prefetch();\n }\n if (store.getStructured) {\n const structured = store.getStructured();\n if (structured && Object.keys(structured).length > 0) {\n return structured as InferSchema<S>;\n }\n }\n return flattenSchema(options.schema ?? {}) as InferSchema<S>;\n },\n\n string(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"string\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n richtext(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"richtext\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n color(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"color\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n image(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"image\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n boolean(key, fallback, opts: VardVariableOptions = {}) {\n return register<boolean>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"boolean\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n group: opts.group,\n });\n },\n\n list<LS extends VardListItemSchema>(\n key: string,\n schema: LS,\n fallback: InferListItem<LS>[],\n opts: VardVariableOptions = {}\n ): InferListItem<LS>[] {\n return register<InferListItem<LS>[]>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"list\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n listItemSchema: schema,\n group: opts.group,\n });\n },\n\n collection<LS extends VardListItemSchema>(\n key: string,\n schema: LS,\n fallback: InferListItem<LS>[],\n opts: Omit<VardVariableOptions, \"type\"> = {}\n ): InferListItem<LS>[] {\n return register<InferListItem<LS>[]>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"list\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n listItemSchema: schema,\n group: opts.group,\n isCollection: true,\n });\n },\n\n global: {\n string(key, fallback, opts = {}) {\n return client.string(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n richtext(key, fallback, opts = {}) {\n return client.richtext(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n color(key, fallback, opts = {}) {\n return client.color(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n image(key, fallback, opts = {}) {\n return client.image(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n boolean(key, fallback, opts = {}) {\n return client.boolean(key, fallback, { ...opts, group: \"Global\" } as Omit<\n VardVariableOptions,\n \"type\"\n >);\n },\n list(key, schema, fallback, opts = {}) {\n return client.list(key, schema, fallback, { ...opts, group: \"Global\" } as Omit<\n VardVariableOptions,\n \"type\"\n >);\n },\n },\n\n extend<E extends VardSchema>(fragment: VardSchemaFragment<E>): VardClient<MergeSchema<S, E>> {\n // Merge the base schema with the fragment — the fragment keys win on collision\n const mergedSchema = { ...(options.schema ?? {}), ...fragment } as unknown as MergeSchema<\n S,\n E\n >;\n // Return a new client with the merged schema, sharing the same store & registry.\n // We pass the in-memory store directly so there is no second fetch.\n return createVard<MergeSchema<S, E>>({\n ...options,\n schema: mergedSchema,\n store,\n });\n },\n\n getDefinitions() {\n return [...registry];\n },\n store,\n };\n\n return client;\n}\n\n// ─────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────\n\nfunction labelFromKey(key: string): string {\n const lastSegment = key.split(\".\").pop() ?? key;\n return lastSegment\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (c) => c.toUpperCase())\n .trim();\n}\n","import { VardVariableType, VardRole } from \"./types\";\n\nexport interface VardFieldOptions<T = any> {\n label?: string;\n description?: string;\n editableBy?: VardRole;\n group?: string;\n default?: T;\n}\n\nexport interface VardField<T = any> extends VardFieldOptions<T> {\n type: VardVariableType;\n}\n\nexport interface VardCollection<S extends Record<string, VardField | any> = any> {\n type: \"collection\";\n schema: S;\n}\n\nexport type VardSchemaValue =\n | VardField\n | VardCollection\n | boolean\n | { [key: string]: VardSchemaValue };\n\nexport type VardSchema = Record<string, VardSchemaValue>;\n\n/**\n * A branded schema fragment created with `v.schema()`. Use with `vard.extend()`\n * to compose schemas defined across multiple files.\n */\nexport type VardSchemaFragment<S extends VardSchema> = S & {\n readonly __fragment: true;\n};\n\n/**\n * Merges two VardSchema types, with B's keys overriding A on collision.\n */\nexport type MergeSchema<A extends VardSchema, B extends VardSchema> = Omit<A, keyof B> & B;\n\n// ─────────────────────────────────────────────\n// The `v` helper object for schema definition\n// ─────────────────────────────────────────────\n\nexport const v = {\n string: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"string\",\n default: defaultValue,\n ...opts,\n }),\n\n richtext: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"richtext\",\n default: defaultValue,\n ...opts,\n }),\n\n color: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"color\",\n default: defaultValue,\n ...opts,\n }),\n\n image: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"image\",\n default: defaultValue,\n ...opts,\n }),\n\n boolean: (\n defaultValue?: boolean,\n opts: Omit<VardFieldOptions<boolean>, \"default\"> = {}\n ): VardField<boolean> => ({\n type: \"boolean\",\n default: defaultValue,\n ...opts,\n }),\n\n collection: <S extends Record<string, VardField | any>>(schema: S): VardCollection<S> => ({\n type: \"collection\",\n schema,\n }),\n\n /**\n * Creates a reusable schema fragment that can be merged into a Vard client\n * via `vard.extend(fragment)`. Co-locate this with your page/component.\n *\n * @example\n * // app/therapists/schema.ts\n * export const therapistSchema = v.schema({\n * therapists: v.collection({ name: v.string(), photo: v.image() }),\n * });\n *\n * // app/therapists/page.tsx\n * const { therapists } = await vard.extend(therapistSchema).get();\n */\n schema: <S extends VardSchema>(schema: S): VardSchemaFragment<S> =>\n schema as VardSchemaFragment<S>,\n};\n\n// ─────────────────────────────────────────────\n// Type inference for schema objects\n// ─────────────────────────────────────────────\n\nexport type InferSchema<T> = 0 extends 1 & T\n ? any\n : T extends VardField<infer U>\n ? U\n : T extends VardCollection<infer S>\n ? InferSchema<S>[]\n : T extends VardSchemaFragment<infer S>\n ? InferSchema<S>\n : T extends Record<string, any>\n ? { [K in keyof T as K extends \"__fragment\" ? never : K]: InferSchema<T[K]> }\n : T;\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  // src/fetch-store.ts
2
2
  function createVardFetchStore(options = {}) {
3
3
  const {
4
- apiBase = options.apiBase ?? process.env.VARD_API_BASE ?? process.env.NEXT_PUBLIC_VARD_API_BASE ?? "https://dash.vard.app",
4
+ apiBase = options.apiBase ?? process.env.VARD_API_HOST ?? "https://dash.vard.app",
5
5
  apiKey = options.apiKey ?? process.env.VARD_API_KEY,
6
- fetchOptions = {}
6
+ fetchOptions = {},
7
+ debug = options.debug ?? false
7
8
  } = options;
8
9
  let resolvedValues = null;
9
10
  let structuredContent = null;
@@ -22,7 +23,14 @@ function createVardFetchStore(options = {}) {
22
23
  }
23
24
  return { variables: /* @__PURE__ */ new Map(), structured: {} };
24
25
  }
25
- const url = `${apiBase}/api/content/variables?structured=true`;
26
+ const url = `${apiBase}/api/content/variables`;
27
+ if (debug) {
28
+ console.log(`[vard] Request: GET ${url}`);
29
+ console.log(`[vard] Headers:`, {
30
+ "X-Vard-API-Key": apiKey.substring(0, 10) + "...",
31
+ ...fetchOptions.headers
32
+ });
33
+ }
26
34
  try {
27
35
  const res = await fetch(url, {
28
36
  ...fetchOptions,
@@ -32,24 +40,39 @@ function createVardFetchStore(options = {}) {
32
40
  }
33
41
  });
34
42
  if (!res.ok) {
35
- console.warn(`[vard] Failed to fetch variables: ${res.status}`);
43
+ const errorMsg = `[vard] Failed to fetch variables from ${url} (Status: ${res.status} ${res.statusText})`;
44
+ console.error(`\x1B[31m${errorMsg}\x1B[0m`);
36
45
  return { variables: /* @__PURE__ */ new Map(), structured: {} };
37
46
  }
38
47
  const data = await res.json();
39
- if (Array.isArray(data)) {
40
- return {
41
- variables: new Map(data.map((v2) => [v2.key, v2.value])),
42
- structured: {}
43
- };
48
+ if (debug) {
49
+ console.log(`[vard] Response (${res.status}):`, data);
44
50
  }
51
+ const variablesMap = /* @__PURE__ */ new Map();
52
+ flattenObject(data, "", variablesMap);
45
53
  return {
46
- variables: new Map(data.variables.map((v2) => [v2.key, v2.value])),
47
- structured: data.structured || {}
54
+ variables: variablesMap,
55
+ structured: data
48
56
  };
49
57
  } catch (err) {
58
+ const errorMsg = `[vard] Network error fetching variables from ${url}`;
59
+ console.error(`\x1B[31m${errorMsg}\x1B[0m`, err);
50
60
  return { variables: /* @__PURE__ */ new Map(), structured: {} };
51
61
  }
52
62
  }
63
+ function flattenObject(obj, prefix, map) {
64
+ if (typeof obj !== "object" || obj === null) return;
65
+ for (const [key, value] of Object.entries(obj)) {
66
+ const fullKey = prefix ? `${prefix}.${key}` : key;
67
+ if (Array.isArray(value)) {
68
+ map.set(fullKey, value);
69
+ } else if (typeof value === "object" && value !== null) {
70
+ flattenObject(value, fullKey, map);
71
+ } else {
72
+ map.set(fullKey, value);
73
+ }
74
+ }
75
+ }
53
76
  return {
54
77
  get(key) {
55
78
  return resolvedValues?.get(key);
@@ -145,7 +168,7 @@ function createVard(options = {}) {
145
168
  if (options.schema && process.env.NODE_ENV === "development" && options.apiKey) {
146
169
  flattenSchema(options.schema);
147
170
  const definitions = [...registry];
148
- const apiBase = process.env.VARD_API_BASE ?? process.env.NEXT_PUBLIC_VARD_API_BASE ?? "https://dash.vard.app";
171
+ const apiBase = process.env.VARD_API_HOST ?? "https://dash.vard.app";
149
172
  fetch(`${apiBase}/api/content/variables/sync`, {
150
173
  method: "POST",
151
174
  headers: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/fetch-store.ts","../src/client.ts","../src/schema.ts"],"sourcesContent":["import type { VardStore } from \"./types\";\n\nexport interface VardFetchStoreOptions {\n /**\n * Base URL of the Vard API. Defaults to https://api.vard.app\n */\n apiBase?: string;\n\n /**\n * API Key for authentication. Defaults to process.env.VARD_API_KEY.\n */\n apiKey?: string;\n\n /**\n * Custom fetch options (headers, etc.)\n */\n fetchOptions?: RequestInit;\n}\n\n/**\n * Creates a universal VardStore that fetches variable values from the Vard API.\n * Works in any environment with a global `fetch` (Browsers, Node 18+, Bun, Deno).\n */\nexport function createVardFetchStore(\n options: VardFetchStoreOptions = {}\n): VardStore & { prefetch(): Promise<void> } {\n const {\n apiBase = options.apiBase ??\n process.env.VARD_API_BASE ??\n process.env.NEXT_PUBLIC_VARD_API_BASE ??\n \"https://dash.vard.app\",\n apiKey = options.apiKey ?? process.env.VARD_API_KEY,\n fetchOptions = {},\n } = options;\n\n let resolvedValues: Map<string, unknown> | null = null;\n let structuredContent: any = null;\n let fetchPromise: Promise<{ variables: Map<string, unknown>; structured: any }> | null = null;\n\n async function fetchValues(): Promise<{ variables: Map<string, unknown>; structured: any }> {\n const isDevelopment = process.env.NODE_ENV === \"development\";\n\n if (!apiKey) {\n if (!isDevelopment) {\n console.error(\n \"\\x1b[31m[vard] Missing configuration! VARD_API_KEY is not set.\\x1b[0m\\n\" +\n \"Please set this environment variable in your production environment.\"\n );\n } else {\n console.warn(\n \"[vard] No API Key found. Running in local fallback mode (using default values).\"\n );\n }\n return { variables: new Map(), structured: {} };\n }\n\n const url = `${apiBase}/api/content/variables?structured=true`;\n\n try {\n const res = await fetch(url, {\n ...fetchOptions,\n headers: {\n ...fetchOptions.headers,\n \"X-Vard-API-Key\": apiKey,\n },\n });\n\n if (!res.ok) {\n console.warn(`[vard] Failed to fetch variables: ${res.status}`);\n return { variables: new Map(), structured: {} };\n }\n\n const data = (await res.json()) as any;\n\n // Handle both legacy (array) and new (object with structured) responses\n if (Array.isArray(data)) {\n return {\n variables: new Map(data.map((v: any) => [v.key, v.value])),\n structured: {},\n };\n }\n\n return {\n variables: new Map(data.variables.map((v: any) => [v.key, v.value])),\n structured: data.structured || {},\n };\n } catch (err) {\n return { variables: new Map(), structured: {} };\n }\n }\n\n return {\n get(key: string): unknown {\n return resolvedValues?.get(key);\n },\n\n getStructured(): any {\n return structuredContent;\n },\n\n async prefetch(): Promise<void> {\n if (resolvedValues) return;\n if (!fetchPromise) {\n fetchPromise = fetchValues();\n }\n const result = await fetchPromise;\n resolvedValues = result.variables;\n structuredContent = result.structured;\n },\n };\n}\n","import {\n VardClient,\n VardOptions,\n VardStore,\n VardVariableDefinition,\n VardVariableOptions,\n VardListItemSchema,\n InferListItem,\n VardRole,\n VardVariableType,\n} from \"./types\";\nimport {\n VardSchema,\n InferSchema,\n VardField,\n VardCollection,\n VardSchemaFragment,\n MergeSchema,\n} from \"./schema\";\nimport { createVardFetchStore } from \"./fetch-store\";\n\n// ─────────────────────────────────────────────\n// No-op store (used in local dev when no apiKey is set)\n// ─────────────────────────────────────────────\n\nlet hasLoggedNoop = false;\nconst noopStore: VardStore = {\n get: () => {\n if (!hasLoggedNoop && process.env.NODE_ENV !== \"test\") {\n console.warn(\n \"[vard] Using default values for all variables because no Store was provided to createVard().\"\n );\n hasLoggedNoop = true;\n }\n return undefined;\n },\n};\n\n// ─────────────────────────────────────────────\n// createVard — the main SDK factory\n// ─────────────────────────────────────────────\n\n/**\n * Creates a Vard client instance. Call this once at the top of your site\n * (e.g. in `lib/vard.ts`) and export the result.\n */\nexport function createVard<S extends VardSchema = any>(\n options: VardOptions<S> = {}\n): VardClient<S> {\n const store: VardStore =\n options.store ?? (options.apiKey ? createVardFetchStore(options) : noopStore);\n\n // Registry of all declared variables — used by CLI + build pipeline\n const registry: VardVariableDefinition[] = [];\n\n function register<T>(def: VardVariableDefinition<T>): T {\n if (!registry.find((d) => d.key === def.key)) {\n registry.push(def as VardVariableDefinition);\n }\n\n const stored = store.get(def.key);\n if (stored !== undefined && stored !== null) {\n return stored as T;\n }\n\n return def.defaultValue;\n }\n\n // ─────────────────────────────────────────────\n // Schema Traversal\n // ─────────────────────────────────────────────\n\n function flattenSchema(schema: VardSchema, prefix = \"\"): any {\n const result: any = {};\n\n for (const [key, value] of Object.entries(schema)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === \"object\" && value !== null && \"type\" in value) {\n // It's a field or collection\n const field = value as VardField | VardCollection;\n\n if (field.type === \"collection\") {\n // Flatten collection schema but keep it as a 'list' type for the registry\n const collection = field as VardCollection;\n const listItemSchema: Record<string, string> = {};\n for (const [fKey, fVal] of Object.entries(collection.schema)) {\n listItemSchema[fKey] = (fVal as VardField).type;\n }\n\n register({\n key: fullKey,\n label: labelFromKey(key),\n type: \"list\",\n defaultValue: [],\n editableBy: \"member\",\n listItemSchema: listItemSchema as VardListItemSchema,\n isCollection: true,\n });\n\n // In the returned object, this remains a placeholder or is proxied to the store\n Object.defineProperty(result, key, {\n get: () => store.get(fullKey) ?? [],\n enumerable: true,\n });\n } else {\n // It's a plain field\n const vardField = field as VardField;\n register({\n key: fullKey,\n label: vardField.label ?? labelFromKey(key),\n description: vardField.description,\n type: vardField.type,\n defaultValue: vardField.default,\n editableBy: vardField.editableBy ?? \"member\",\n group: vardField.group,\n });\n\n Object.defineProperty(result, key, {\n get: () => store.get(fullKey) ?? vardField.default,\n enumerable: true,\n });\n }\n } else if (typeof value === \"object\" && value !== null) {\n // It's a nested object\n result[key] = flattenSchema(value as VardSchema, fullKey);\n }\n }\n\n return result;\n }\n\n // Auto-sync schema in development\n if (options.schema && process.env.NODE_ENV === \"development\" && options.apiKey) {\n flattenSchema(options.schema);\n const definitions = [...registry];\n const apiBase =\n process.env.VARD_API_BASE ?? process.env.NEXT_PUBLIC_VARD_API_BASE ?? \"https://dash.vard.app\";\n\n fetch(`${apiBase}/api/content/variables/sync`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Vard-API-Key\": options.apiKey,\n },\n body: JSON.stringify({\n definitions,\n schema: options.schema,\n }),\n }).catch((err) => console.warn(\"[vard] Auto-sync failed:\", err));\n }\n\n const client: VardClient<S> = {\n define<NS extends VardSchema>(schema: NS): InferSchema<NS> {\n return flattenSchema(schema) as InferSchema<NS>;\n },\n\n async get(): Promise<InferSchema<S>> {\n if (store.prefetch) {\n await store.prefetch();\n }\n if (store.getStructured) {\n const structured = store.getStructured();\n if (structured && Object.keys(structured).length > 0) {\n return structured as InferSchema<S>;\n }\n }\n return flattenSchema(options.schema ?? {}) as InferSchema<S>;\n },\n\n string(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"string\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n richtext(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"richtext\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n color(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"color\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n image(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"image\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n boolean(key, fallback, opts: VardVariableOptions = {}) {\n return register<boolean>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"boolean\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n group: opts.group,\n });\n },\n\n list<LS extends VardListItemSchema>(\n key: string,\n schema: LS,\n fallback: InferListItem<LS>[],\n opts: VardVariableOptions = {}\n ): InferListItem<LS>[] {\n return register<InferListItem<LS>[]>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"list\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n listItemSchema: schema,\n group: opts.group,\n });\n },\n\n collection<LS extends VardListItemSchema>(\n key: string,\n schema: LS,\n fallback: InferListItem<LS>[],\n opts: Omit<VardVariableOptions, \"type\"> = {}\n ): InferListItem<LS>[] {\n return register<InferListItem<LS>[]>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"list\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n listItemSchema: schema,\n group: opts.group,\n isCollection: true,\n });\n },\n\n global: {\n string(key, fallback, opts = {}) {\n return client.string(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n richtext(key, fallback, opts = {}) {\n return client.richtext(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n color(key, fallback, opts = {}) {\n return client.color(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n image(key, fallback, opts = {}) {\n return client.image(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n boolean(key, fallback, opts = {}) {\n return client.boolean(key, fallback, { ...opts, group: \"Global\" } as Omit<\n VardVariableOptions,\n \"type\"\n >);\n },\n list(key, schema, fallback, opts = {}) {\n return client.list(key, schema, fallback, { ...opts, group: \"Global\" } as Omit<\n VardVariableOptions,\n \"type\"\n >);\n },\n },\n\n extend<E extends VardSchema>(fragment: VardSchemaFragment<E>): VardClient<MergeSchema<S, E>> {\n // Merge the base schema with the fragment — the fragment keys win on collision\n const mergedSchema = { ...(options.schema ?? {}), ...fragment } as unknown as MergeSchema<\n S,\n E\n >;\n // Return a new client with the merged schema, sharing the same store & registry.\n // We pass the in-memory store directly so there is no second fetch.\n return createVard<MergeSchema<S, E>>({\n ...options,\n schema: mergedSchema,\n store,\n });\n },\n\n getDefinitions() {\n return [...registry];\n },\n store,\n };\n\n return client;\n}\n\n// ─────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────\n\nfunction labelFromKey(key: string): string {\n const lastSegment = key.split(\".\").pop() ?? key;\n return lastSegment\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (c) => c.toUpperCase())\n .trim();\n}\n","import { VardVariableType, VardRole } from \"./types\";\n\nexport interface VardFieldOptions<T = any> {\n label?: string;\n description?: string;\n editableBy?: VardRole;\n group?: string;\n default?: T;\n}\n\nexport interface VardField<T = any> extends VardFieldOptions<T> {\n type: VardVariableType;\n}\n\nexport interface VardCollection<S extends Record<string, VardField | any> = any> {\n type: \"collection\";\n schema: S;\n}\n\nexport type VardSchemaValue = VardField | VardCollection | { [key: string]: VardSchemaValue };\n\nexport type VardSchema = Record<string, VardSchemaValue>;\n\n/**\n * A branded schema fragment created with `v.schema()`. Use with `vard.extend()`\n * to compose schemas defined across multiple files.\n */\nexport type VardSchemaFragment<S extends VardSchema> = S & {\n readonly __fragment: true;\n};\n\n/**\n * Merges two VardSchema types, with B's keys overriding A on collision.\n */\nexport type MergeSchema<A extends VardSchema, B extends VardSchema> = Omit<A, keyof B> & B;\n\n// ─────────────────────────────────────────────\n// The `v` helper object for schema definition\n// ─────────────────────────────────────────────\n\nexport const v = {\n string: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"string\",\n default: defaultValue,\n ...opts,\n }),\n\n richtext: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"richtext\",\n default: defaultValue,\n ...opts,\n }),\n\n color: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"color\",\n default: defaultValue,\n ...opts,\n }),\n\n image: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"image\",\n default: defaultValue,\n ...opts,\n }),\n\n boolean: (\n defaultValue?: boolean,\n opts: Omit<VardFieldOptions<boolean>, \"default\"> = {}\n ): VardField<boolean> => ({\n type: \"boolean\",\n default: defaultValue,\n ...opts,\n }),\n\n collection: <S extends Record<string, VardField | any>>(schema: S): VardCollection<S> => ({\n type: \"collection\",\n schema,\n }),\n\n /**\n * Creates a reusable schema fragment that can be merged into a Vard client\n * via `vard.extend(fragment)`. Co-locate this with your page/component.\n *\n * @example\n * // app/therapists/schema.ts\n * export const therapistSchema = v.schema({\n * therapists: v.collection({ name: v.string(), photo: v.image() }),\n * });\n *\n * // app/therapists/page.tsx\n * const { therapists } = await vard.extend(therapistSchema).get();\n */\n schema: <S extends VardSchema>(schema: S): VardSchemaFragment<S> =>\n schema as VardSchemaFragment<S>,\n};\n\n// ─────────────────────────────────────────────\n// Type inference for schema objects\n// ─────────────────────────────────────────────\n\nexport type InferSchema<T> = {\n [K in keyof T]: T[K] extends VardField<infer U>\n ? U\n : T[K] extends VardCollection<infer S>\n ? InferSchema<S>[]\n : T[K] extends object\n ? InferSchema<T[K]>\n : never;\n};\n"],"mappings":";AAuBO,SAAS,qBACd,UAAiC,CAAC,GACS;AAC3C,QAAM;AAAA,IACJ,UAAU,QAAQ,WAChB,QAAQ,IAAI,iBACZ,QAAQ,IAAI,6BACZ;AAAA,IACF,SAAS,QAAQ,UAAU,QAAQ,IAAI;AAAA,IACvC,eAAe,CAAC;AAAA,EAClB,IAAI;AAEJ,MAAI,iBAA8C;AAClD,MAAI,oBAAyB;AAC7B,MAAI,eAAqF;AAEzF,iBAAe,cAA6E;AAC1F,UAAM,gBAAgB,QAAQ,IAAI,aAAa;AAE/C,QAAI,CAAC,QAAQ;AACX,UAAI,CAAC,eAAe;AAClB,gBAAQ;AAAA,UACN;AAAA,QAEF;AAAA,MACF,OAAO;AACL,gBAAQ;AAAA,UACN;AAAA,QACF;AAAA,MACF;AACA,aAAO,EAAE,WAAW,oBAAI,IAAI,GAAG,YAAY,CAAC,EAAE;AAAA,IAChD;AAEA,UAAM,MAAM,GAAG,OAAO;AAEtB,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,KAAK;AAAA,QAC3B,GAAG;AAAA,QACH,SAAS;AAAA,UACP,GAAG,aAAa;AAAA,UAChB,kBAAkB;AAAA,QACpB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,IAAI,IAAI;AACX,gBAAQ,KAAK,qCAAqC,IAAI,MAAM,EAAE;AAC9D,eAAO,EAAE,WAAW,oBAAI,IAAI,GAAG,YAAY,CAAC,EAAE;AAAA,MAChD;AAEA,YAAM,OAAQ,MAAM,IAAI,KAAK;AAG7B,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,eAAO;AAAA,UACL,WAAW,IAAI,IAAI,KAAK,IAAI,CAACA,OAAW,CAACA,GAAE,KAAKA,GAAE,KAAK,CAAC,CAAC;AAAA,UACzD,YAAY,CAAC;AAAA,QACf;AAAA,MACF;AAEA,aAAO;AAAA,QACL,WAAW,IAAI,IAAI,KAAK,UAAU,IAAI,CAACA,OAAW,CAACA,GAAE,KAAKA,GAAE,KAAK,CAAC,CAAC;AAAA,QACnE,YAAY,KAAK,cAAc,CAAC;AAAA,MAClC;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,EAAE,WAAW,oBAAI,IAAI,GAAG,YAAY,CAAC,EAAE;AAAA,IAChD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,IAAI,KAAsB;AACxB,aAAO,gBAAgB,IAAI,GAAG;AAAA,IAChC;AAAA,IAEA,gBAAqB;AACnB,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,WAA0B;AAC9B,UAAI,eAAgB;AACpB,UAAI,CAAC,cAAc;AACjB,uBAAe,YAAY;AAAA,MAC7B;AACA,YAAM,SAAS,MAAM;AACrB,uBAAiB,OAAO;AACxB,0BAAoB,OAAO;AAAA,IAC7B;AAAA,EACF;AACF;;;ACrFA,IAAI,gBAAgB;AACpB,IAAM,YAAuB;AAAA,EAC3B,KAAK,MAAM;AACT,QAAI,CAAC,iBAAiB,QAAQ,IAAI,aAAa,QAAQ;AACrD,cAAQ;AAAA,QACN;AAAA,MACF;AACA,sBAAgB;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AACF;AAUO,SAAS,WACd,UAA0B,CAAC,GACZ;AACf,QAAM,QACJ,QAAQ,UAAU,QAAQ,SAAS,qBAAqB,OAAO,IAAI;AAGrE,QAAM,WAAqC,CAAC;AAE5C,WAAS,SAAY,KAAmC;AACtD,QAAI,CAAC,SAAS,KAAK,CAAC,MAAM,EAAE,QAAQ,IAAI,GAAG,GAAG;AAC5C,eAAS,KAAK,GAA6B;AAAA,IAC7C;AAEA,UAAM,SAAS,MAAM,IAAI,IAAI,GAAG;AAChC,QAAI,WAAW,UAAa,WAAW,MAAM;AAC3C,aAAO;AAAA,IACT;AAEA,WAAO,IAAI;AAAA,EACb;AAMA,WAAS,cAAc,QAAoB,SAAS,IAAS;AAC3D,UAAM,SAAc,CAAC;AAErB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,YAAM,UAAU,SAAS,GAAG,MAAM,IAAI,GAAG,KAAK;AAE9C,UAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,OAAO;AAElE,cAAM,QAAQ;AAEd,YAAI,MAAM,SAAS,cAAc;AAE/B,gBAAM,aAAa;AACnB,gBAAM,iBAAyC,CAAC;AAChD,qBAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,WAAW,MAAM,GAAG;AAC5D,2BAAe,IAAI,IAAK,KAAmB;AAAA,UAC7C;AAEA,mBAAS;AAAA,YACP,KAAK;AAAA,YACL,OAAO,aAAa,GAAG;AAAA,YACvB,MAAM;AAAA,YACN,cAAc,CAAC;AAAA,YACf,YAAY;AAAA,YACZ;AAAA,YACA,cAAc;AAAA,UAChB,CAAC;AAGD,iBAAO,eAAe,QAAQ,KAAK;AAAA,YACjC,KAAK,MAAM,MAAM,IAAI,OAAO,KAAK,CAAC;AAAA,YAClC,YAAY;AAAA,UACd,CAAC;AAAA,QACH,OAAO;AAEL,gBAAM,YAAY;AAClB,mBAAS;AAAA,YACP,KAAK;AAAA,YACL,OAAO,UAAU,SAAS,aAAa,GAAG;AAAA,YAC1C,aAAa,UAAU;AAAA,YACvB,MAAM,UAAU;AAAA,YAChB,cAAc,UAAU;AAAA,YACxB,YAAY,UAAU,cAAc;AAAA,YACpC,OAAO,UAAU;AAAA,UACnB,CAAC;AAED,iBAAO,eAAe,QAAQ,KAAK;AAAA,YACjC,KAAK,MAAM,MAAM,IAAI,OAAO,KAAK,UAAU;AAAA,YAC3C,YAAY;AAAA,UACd,CAAC;AAAA,QACH;AAAA,MACF,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AAEtD,eAAO,GAAG,IAAI,cAAc,OAAqB,OAAO;AAAA,MAC1D;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,UAAU,QAAQ,IAAI,aAAa,iBAAiB,QAAQ,QAAQ;AAC9E,kBAAc,QAAQ,MAAM;AAC5B,UAAM,cAAc,CAAC,GAAG,QAAQ;AAChC,UAAM,UACJ,QAAQ,IAAI,iBAAiB,QAAQ,IAAI,6BAA6B;AAExE,UAAM,GAAG,OAAO,+BAA+B;AAAA,MAC7C,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,kBAAkB,QAAQ;AAAA,MAC5B;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB;AAAA,QACA,QAAQ,QAAQ;AAAA,MAClB,CAAC;AAAA,IACH,CAAC,EAAE,MAAM,CAAC,QAAQ,QAAQ,KAAK,4BAA4B,GAAG,CAAC;AAAA,EACjE;AAEA,QAAM,SAAwB;AAAA,IAC5B,OAA8B,QAA6B;AACzD,aAAO,cAAc,MAAM;AAAA,IAC7B;AAAA,IAEA,MAAM,MAA+B;AACnC,UAAI,MAAM,UAAU;AAClB,cAAM,MAAM,SAAS;AAAA,MACvB;AACA,UAAI,MAAM,eAAe;AACvB,cAAM,aAAa,MAAM,cAAc;AACvC,YAAI,cAAc,OAAO,KAAK,UAAU,EAAE,SAAS,GAAG;AACpD,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO,cAAc,QAAQ,UAAU,CAAC,CAAC;AAAA,IAC3C;AAAA,IAEA,OAAO,KAAK,UAAU,OAA4B,CAAC,GAAG;AACpD,aAAO,SAAiB;AAAA,QACtB;AAAA,QACA,OAAO,KAAK,SAAS,aAAa,GAAG;AAAA,QACrC,aAAa,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,cAAc;AAAA,QACd,YAAY,KAAK,cAAc;AAAA,QAC/B,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH;AAAA,IAEA,SAAS,KAAK,UAAU,OAA4B,CAAC,GAAG;AACtD,aAAO,SAAiB;AAAA,QACtB;AAAA,QACA,OAAO,KAAK,SAAS,aAAa,GAAG;AAAA,QACrC,aAAa,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,cAAc;AAAA,QACd,YAAY,KAAK,cAAc;AAAA,QAC/B,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,KAAK,UAAU,OAA4B,CAAC,GAAG;AACnD,aAAO,SAAiB;AAAA,QACtB;AAAA,QACA,OAAO,KAAK,SAAS,aAAa,GAAG;AAAA,QACrC,aAAa,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,cAAc;AAAA,QACd,YAAY,KAAK,cAAc;AAAA,QAC/B,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH;AAAA,IAEA,MAAM,KAAK,UAAU,OAA4B,CAAC,GAAG;AACnD,aAAO,SAAiB;AAAA,QACtB;AAAA,QACA,OAAO,KAAK,SAAS,aAAa,GAAG;AAAA,QACrC,aAAa,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,cAAc;AAAA,QACd,YAAY,KAAK,cAAc;AAAA,QAC/B,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH;AAAA,IAEA,QAAQ,KAAK,UAAU,OAA4B,CAAC,GAAG;AACrD,aAAO,SAAkB;AAAA,QACvB;AAAA,QACA,OAAO,KAAK,SAAS,aAAa,GAAG;AAAA,QACrC,aAAa,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,cAAc;AAAA,QACd,YAAa,KAAK,cAA2B;AAAA,QAC7C,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH;AAAA,IAEA,KACE,KACA,QACA,UACA,OAA4B,CAAC,GACR;AACrB,aAAO,SAA8B;AAAA,QACnC;AAAA,QACA,OAAO,KAAK,SAAS,aAAa,GAAG;AAAA,QACrC,aAAa,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,cAAc;AAAA,QACd,YAAa,KAAK,cAA2B;AAAA,QAC7C,gBAAgB;AAAA,QAChB,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH;AAAA,IAEA,WACE,KACA,QACA,UACA,OAA0C,CAAC,GACtB;AACrB,aAAO,SAA8B;AAAA,QACnC;AAAA,QACA,OAAO,KAAK,SAAS,aAAa,GAAG;AAAA,QACrC,aAAa,KAAK;AAAA,QAClB,MAAM;AAAA,QACN,cAAc;AAAA,QACd,YAAa,KAAK,cAA2B;AAAA,QAC7C,gBAAgB;AAAA,QAChB,OAAO,KAAK;AAAA,QACZ,cAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,IAEA,QAAQ;AAAA,MACN,OAAO,KAAK,UAAU,OAAO,CAAC,GAAG;AAC/B,eAAO,OAAO,OAAO,KAAK,UAAU,EAAE,GAAG,MAAM,OAAO,SAAS,CAAwB;AAAA,MACzF;AAAA,MACA,SAAS,KAAK,UAAU,OAAO,CAAC,GAAG;AACjC,eAAO,OAAO,SAAS,KAAK,UAAU,EAAE,GAAG,MAAM,OAAO,SAAS,CAAwB;AAAA,MAC3F;AAAA,MACA,MAAM,KAAK,UAAU,OAAO,CAAC,GAAG;AAC9B,eAAO,OAAO,MAAM,KAAK,UAAU,EAAE,GAAG,MAAM,OAAO,SAAS,CAAwB;AAAA,MACxF;AAAA,MACA,MAAM,KAAK,UAAU,OAAO,CAAC,GAAG;AAC9B,eAAO,OAAO,MAAM,KAAK,UAAU,EAAE,GAAG,MAAM,OAAO,SAAS,CAAwB;AAAA,MACxF;AAAA,MACA,QAAQ,KAAK,UAAU,OAAO,CAAC,GAAG;AAChC,eAAO,OAAO,QAAQ,KAAK,UAAU,EAAE,GAAG,MAAM,OAAO,SAAS,CAG/D;AAAA,MACH;AAAA,MACA,KAAK,KAAK,QAAQ,UAAU,OAAO,CAAC,GAAG;AACrC,eAAO,OAAO,KAAK,KAAK,QAAQ,UAAU,EAAE,GAAG,MAAM,OAAO,SAAS,CAGpE;AAAA,MACH;AAAA,IACF;AAAA,IAEA,OAA6B,UAAgE;AAE3F,YAAM,eAAe,EAAE,GAAI,QAAQ,UAAU,CAAC,GAAI,GAAG,SAAS;AAM9D,aAAO,WAA8B;AAAA,QACnC,GAAG;AAAA,QACH,QAAQ;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,iBAAiB;AACf,aAAO,CAAC,GAAG,QAAQ;AAAA,IACrB;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,aAAa,KAAqB;AACzC,QAAM,cAAc,IAAI,MAAM,GAAG,EAAE,IAAI,KAAK;AAC5C,SAAO,YACJ,QAAQ,YAAY,KAAK,EACzB,QAAQ,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EACpC,KAAK;AACV;;;AChSO,IAAM,IAAI;AAAA,EACf,QAAQ,CACN,cACA,OAAkD,CAAC,OAC5B;AAAA,IACvB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,GAAG;AAAA,EACL;AAAA,EAEA,UAAU,CACR,cACA,OAAkD,CAAC,OAC5B;AAAA,IACvB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,GAAG;AAAA,EACL;AAAA,EAEA,OAAO,CACL,cACA,OAAkD,CAAC,OAC5B;AAAA,IACvB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,GAAG;AAAA,EACL;AAAA,EAEA,OAAO,CACL,cACA,OAAkD,CAAC,OAC5B;AAAA,IACvB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,GAAG;AAAA,EACL;AAAA,EAEA,SAAS,CACP,cACA,OAAmD,CAAC,OAC5B;AAAA,IACxB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,GAAG;AAAA,EACL;AAAA,EAEA,YAAY,CAA4C,YAAkC;AAAA,IACxF,MAAM;AAAA,IACN;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,QAAQ,CAAuB,WAC7B;AACJ;","names":["v"]}
1
+ {"version":3,"sources":["../src/fetch-store.ts","../src/client.ts","../src/schema.ts"],"sourcesContent":["import type { VardStore } from \"./types\";\n\nexport interface VardFetchStoreOptions {\n /**\n * Base URL of the Vard API. Defaults to https://api.vard.app\n */\n apiBase?: string;\n\n /**\n * API Key for authentication. Defaults to process.env.VARD_API_KEY.\n */\n apiKey?: string;\n\n /**\n * Custom fetch options (headers, etc.)\n */\n fetchOptions?: RequestInit;\n\n /**\n * Enable verbose logging for requests and responses.\n */\n debug?: boolean;\n}\n\n/**\n * Creates a universal VardStore that fetches variable values from the Vard API.\n * Works in any environment with a global `fetch` (Browsers, Node 18+, Bun, Deno).\n */\nexport function createVardFetchStore(\n options: VardFetchStoreOptions = {}\n): VardStore & { prefetch(): Promise<void> } {\n const {\n apiBase = options.apiBase ??\n process.env.VARD_API_HOST ??\n \"https://dash.vard.app\",\n apiKey = options.apiKey ?? process.env.VARD_API_KEY,\n fetchOptions = {},\n debug = options.debug ?? false,\n } = options;\n\n let resolvedValues: Map<string, unknown> | null = null;\n let structuredContent: any = null;\n let fetchPromise: Promise<{ variables: Map<string, unknown>; structured: any }> | null = null;\n\n async function fetchValues(): Promise<{ variables: Map<string, unknown>; structured: any }> {\n const isDevelopment = process.env.NODE_ENV === \"development\";\n\n if (!apiKey) {\n if (!isDevelopment) {\n console.error(\n \"\\x1b[31m[vard] Missing configuration! VARD_API_KEY is not set.\\x1b[0m\\n\" +\n \"Please set this environment variable in your production environment.\"\n );\n } else {\n console.warn(\n \"[vard] No API Key found. Running in local fallback mode (using default values).\"\n );\n }\n return { variables: new Map(), structured: {} };\n }\n\n const url = `${apiBase}/api/content/variables`;\n\n if (debug) {\n console.log(`[vard] Request: GET ${url}`);\n console.log(`[vard] Headers:`, {\n \"X-Vard-API-Key\": apiKey.substring(0, 10) + \"...\",\n ...fetchOptions.headers,\n });\n }\n\n try {\n const res = await fetch(url, {\n ...fetchOptions,\n headers: {\n ...fetchOptions.headers,\n \"X-Vard-API-Key\": apiKey,\n },\n });\n\n if (!res.ok) {\n const errorMsg = `[vard] Failed to fetch variables from ${url} (Status: ${res.status} ${res.statusText})`;\n console.error(`\\x1b[31m${errorMsg}\\x1b[0m`);\n return { variables: new Map(), structured: {} };\n }\n\n const data = (await res.json()) as Record<string, unknown>;\n\n if (debug) {\n console.log(`[vard] Response (${res.status}):`, data);\n }\n\n // Flatten the nested structure into the internal Map for key-based lookups\n const variablesMap = new Map<string, unknown>();\n flattenObject(data, \"\", variablesMap);\n\n return {\n variables: variablesMap,\n structured: data,\n };\n } catch (err) {\n const errorMsg = `[vard] Network error fetching variables from ${url}`;\n console.error(`\\x1b[31m${errorMsg}\\x1b[0m`, err);\n return { variables: new Map(), structured: {} };\n }\n }\n\n function flattenObject(obj: any, prefix: string, map: Map<string, unknown>) {\n if (typeof obj !== \"object\" || obj === null) return;\n\n for (const [key, value] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n // If it's an array, we treat it as a single value (e.g. a collection)\n if (Array.isArray(value)) {\n map.set(fullKey, value);\n } else if (typeof value === \"object\" && value !== null) {\n flattenObject(value, fullKey, map);\n } else {\n map.set(fullKey, value);\n }\n }\n }\n\n return {\n get(key: string): unknown {\n return resolvedValues?.get(key);\n },\n\n getStructured(): any {\n return structuredContent;\n },\n\n async prefetch(): Promise<void> {\n if (resolvedValues) return;\n if (!fetchPromise) {\n fetchPromise = fetchValues();\n }\n const result = await fetchPromise;\n resolvedValues = result.variables;\n structuredContent = result.structured;\n },\n };\n}\n","import {\n VardClient,\n VardOptions,\n VardStore,\n VardVariableDefinition,\n VardVariableOptions,\n VardListItemSchema,\n InferListItem,\n VardRole,\n VardVariableType,\n} from \"./types\";\nimport {\n VardSchema,\n InferSchema,\n VardField,\n VardCollection,\n VardSchemaFragment,\n MergeSchema,\n} from \"./schema\";\nimport { createVardFetchStore } from \"./fetch-store\";\n\n// ─────────────────────────────────────────────\n// No-op store (used in local dev when no apiKey is set)\n// ─────────────────────────────────────────────\n\nlet hasLoggedNoop = false;\nconst noopStore: VardStore = {\n get: () => {\n if (!hasLoggedNoop && process.env.NODE_ENV !== \"test\") {\n console.warn(\n \"[vard] Using default values for all variables because no Store was provided to createVard().\"\n );\n hasLoggedNoop = true;\n }\n return undefined;\n },\n};\n\n// ─────────────────────────────────────────────\n// createVard — the main SDK factory\n// ─────────────────────────────────────────────\n\n/**\n * Creates a Vard client instance. Call this once at the top of your site\n * (e.g. in `lib/vard.ts`) and export the result.\n */\nexport function createVard<S extends VardSchema = any>(\n options: VardOptions<S> = {}\n): VardClient<S> {\n const store: VardStore =\n options.store ?? (options.apiKey ? createVardFetchStore(options) : noopStore);\n\n // Registry of all declared variables — used by CLI + build pipeline\n const registry: VardVariableDefinition[] = [];\n\n function register<T>(def: VardVariableDefinition<T>): T {\n if (!registry.find((d) => d.key === def.key)) {\n registry.push(def as VardVariableDefinition);\n }\n\n const stored = store.get(def.key);\n if (stored !== undefined && stored !== null) {\n return stored as T;\n }\n\n return def.defaultValue;\n }\n\n // ─────────────────────────────────────────────\n // Schema Traversal\n // ─────────────────────────────────────────────\n\n function flattenSchema(schema: VardSchema, prefix = \"\"): any {\n const result: any = {};\n\n for (const [key, value] of Object.entries(schema)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (typeof value === \"object\" && value !== null && \"type\" in value) {\n // It's a field or collection\n const field = value as VardField | VardCollection;\n\n if (field.type === \"collection\") {\n // Flatten collection schema but keep it as a 'list' type for the registry\n const collection = field as VardCollection;\n const listItemSchema: Record<string, string> = {};\n for (const [fKey, fVal] of Object.entries(collection.schema)) {\n listItemSchema[fKey] = (fVal as VardField).type;\n }\n\n register({\n key: fullKey,\n label: labelFromKey(key),\n type: \"list\",\n defaultValue: [],\n editableBy: \"member\",\n listItemSchema: listItemSchema as VardListItemSchema,\n isCollection: true,\n });\n\n // In the returned object, this remains a placeholder or is proxied to the store\n Object.defineProperty(result, key, {\n get: () => store.get(fullKey) ?? [],\n enumerable: true,\n });\n } else {\n // It's a plain field\n const vardField = field as VardField;\n register({\n key: fullKey,\n label: vardField.label ?? labelFromKey(key),\n description: vardField.description,\n type: vardField.type,\n defaultValue: vardField.default,\n editableBy: vardField.editableBy ?? \"member\",\n group: vardField.group,\n });\n\n Object.defineProperty(result, key, {\n get: () => store.get(fullKey) ?? vardField.default,\n enumerable: true,\n });\n }\n } else if (typeof value === \"object\" && value !== null) {\n // It's a nested object\n result[key] = flattenSchema(value as VardSchema, fullKey);\n }\n }\n\n return result;\n }\n\n // Auto-sync schema in development\n if (options.schema && process.env.NODE_ENV === \"development\" && options.apiKey) {\n flattenSchema(options.schema);\n const definitions = [...registry];\n const apiBase = process.env.VARD_API_HOST ?? \"https://dash.vard.app\";\n\n fetch(`${apiBase}/api/content/variables/sync`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Vard-API-Key\": options.apiKey,\n },\n body: JSON.stringify({\n definitions,\n schema: options.schema,\n }),\n }).catch((err) => console.warn(\"[vard] Auto-sync failed:\", err));\n }\n\n const client: VardClient<S> = {\n define<NS extends VardSchema>(schema: NS): InferSchema<NS> {\n return flattenSchema(schema) as InferSchema<NS>;\n },\n\n async get(): Promise<InferSchema<S>> {\n if (store.prefetch) {\n await store.prefetch();\n }\n if (store.getStructured) {\n const structured = store.getStructured();\n if (structured && Object.keys(structured).length > 0) {\n return structured as InferSchema<S>;\n }\n }\n return flattenSchema(options.schema ?? {}) as InferSchema<S>;\n },\n\n string(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"string\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n richtext(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"richtext\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n color(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"color\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n image(key, fallback, opts: VardVariableOptions = {}) {\n return register<string>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"image\",\n defaultValue: fallback,\n editableBy: opts.editableBy ?? \"member\",\n group: opts.group,\n });\n },\n\n boolean(key, fallback, opts: VardVariableOptions = {}) {\n return register<boolean>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"boolean\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n group: opts.group,\n });\n },\n\n list<LS extends VardListItemSchema>(\n key: string,\n schema: LS,\n fallback: InferListItem<LS>[],\n opts: VardVariableOptions = {}\n ): InferListItem<LS>[] {\n return register<InferListItem<LS>[]>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"list\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n listItemSchema: schema,\n group: opts.group,\n });\n },\n\n collection<LS extends VardListItemSchema>(\n key: string,\n schema: LS,\n fallback: InferListItem<LS>[],\n opts: Omit<VardVariableOptions, \"type\"> = {}\n ): InferListItem<LS>[] {\n return register<InferListItem<LS>[]>({\n key,\n label: opts.label ?? labelFromKey(key),\n description: opts.description,\n type: \"list\",\n defaultValue: fallback,\n editableBy: (opts.editableBy as VardRole) ?? \"member\",\n listItemSchema: schema,\n group: opts.group,\n isCollection: true,\n });\n },\n\n global: {\n string(key, fallback, opts = {}) {\n return client.string(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n richtext(key, fallback, opts = {}) {\n return client.richtext(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n color(key, fallback, opts = {}) {\n return client.color(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n image(key, fallback, opts = {}) {\n return client.image(key, fallback, { ...opts, group: \"Global\" } as VardVariableOptions);\n },\n boolean(key, fallback, opts = {}) {\n return client.boolean(key, fallback, { ...opts, group: \"Global\" } as Omit<\n VardVariableOptions,\n \"type\"\n >);\n },\n list(key, schema, fallback, opts = {}) {\n return client.list(key, schema, fallback, { ...opts, group: \"Global\" } as Omit<\n VardVariableOptions,\n \"type\"\n >);\n },\n },\n\n extend<E extends VardSchema>(fragment: VardSchemaFragment<E>): VardClient<MergeSchema<S, E>> {\n // Merge the base schema with the fragment — the fragment keys win on collision\n const mergedSchema = { ...(options.schema ?? {}), ...fragment } as unknown as MergeSchema<\n S,\n E\n >;\n // Return a new client with the merged schema, sharing the same store & registry.\n // We pass the in-memory store directly so there is no second fetch.\n return createVard<MergeSchema<S, E>>({\n ...options,\n schema: mergedSchema,\n store,\n });\n },\n\n getDefinitions() {\n return [...registry];\n },\n store,\n };\n\n return client;\n}\n\n// ─────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────\n\nfunction labelFromKey(key: string): string {\n const lastSegment = key.split(\".\").pop() ?? key;\n return lastSegment\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (c) => c.toUpperCase())\n .trim();\n}\n","import { VardVariableType, VardRole } from \"./types\";\n\nexport interface VardFieldOptions<T = any> {\n label?: string;\n description?: string;\n editableBy?: VardRole;\n group?: string;\n default?: T;\n}\n\nexport interface VardField<T = any> extends VardFieldOptions<T> {\n type: VardVariableType;\n}\n\nexport interface VardCollection<S extends Record<string, VardField | any> = any> {\n type: \"collection\";\n schema: S;\n}\n\nexport type VardSchemaValue =\n | VardField\n | VardCollection\n | boolean\n | { [key: string]: VardSchemaValue };\n\nexport type VardSchema = Record<string, VardSchemaValue>;\n\n/**\n * A branded schema fragment created with `v.schema()`. Use with `vard.extend()`\n * to compose schemas defined across multiple files.\n */\nexport type VardSchemaFragment<S extends VardSchema> = S & {\n readonly __fragment: true;\n};\n\n/**\n * Merges two VardSchema types, with B's keys overriding A on collision.\n */\nexport type MergeSchema<A extends VardSchema, B extends VardSchema> = Omit<A, keyof B> & B;\n\n// ─────────────────────────────────────────────\n// The `v` helper object for schema definition\n// ─────────────────────────────────────────────\n\nexport const v = {\n string: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"string\",\n default: defaultValue,\n ...opts,\n }),\n\n richtext: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"richtext\",\n default: defaultValue,\n ...opts,\n }),\n\n color: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"color\",\n default: defaultValue,\n ...opts,\n }),\n\n image: (\n defaultValue?: string,\n opts: Omit<VardFieldOptions<string>, \"default\"> = {}\n ): VardField<string> => ({\n type: \"image\",\n default: defaultValue,\n ...opts,\n }),\n\n boolean: (\n defaultValue?: boolean,\n opts: Omit<VardFieldOptions<boolean>, \"default\"> = {}\n ): VardField<boolean> => ({\n type: \"boolean\",\n default: defaultValue,\n ...opts,\n }),\n\n collection: <S extends Record<string, VardField | any>>(schema: S): VardCollection<S> => ({\n type: \"collection\",\n schema,\n }),\n\n /**\n * Creates a reusable schema fragment that can be merged into a Vard client\n * via `vard.extend(fragment)`. Co-locate this with your page/component.\n *\n * @example\n * // app/therapists/schema.ts\n * export const therapistSchema = v.schema({\n * therapists: v.collection({ name: v.string(), photo: v.image() }),\n * });\n *\n * // app/therapists/page.tsx\n * const { therapists } = await vard.extend(therapistSchema).get();\n */\n schema: <S extends VardSchema>(schema: S): VardSchemaFragment<S> =>\n schema as VardSchemaFragment<S>,\n};\n\n// ─────────────────────────────────────────────\n// Type inference for schema objects\n// ─────────────────────────────────────────────\n\nexport type InferSchema<T> = 0 extends 1 & T\n ? any\n : T extends VardField<infer U>\n ? U\n : T extends VardCollection<infer S>\n ? InferSchema<S>[]\n : T extends VardSchemaFragment<infer S>\n ? InferSchema<S>\n : T extends Record<string, any>\n ? { [K in keyof T as K extends \"__fragment\" ? never : K]: InferSchema<T[K]> }\n : T;\n"],"mappings":"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","names":[]}
package/dist/next.d.mts CHANGED
@@ -1,4 +1,181 @@
1
- import { a as VardOptions, b as VardClient, c as VardStore } from './types-Dd-I7jwP.mjs';
1
+ interface VardFieldOptions<T = any> {
2
+ label?: string;
3
+ description?: string;
4
+ editableBy?: VardRole;
5
+ group?: string;
6
+ default?: T;
7
+ }
8
+ interface VardField<T = any> extends VardFieldOptions<T> {
9
+ type: VardVariableType;
10
+ }
11
+ interface VardCollection<S extends Record<string, VardField | any> = any> {
12
+ type: "collection";
13
+ schema: S;
14
+ }
15
+ type VardSchemaValue = VardField | VardCollection | boolean | {
16
+ [key: string]: VardSchemaValue;
17
+ };
18
+ type VardSchema = Record<string, VardSchemaValue>;
19
+ /**
20
+ * A branded schema fragment created with `v.schema()`. Use with `vard.extend()`
21
+ * to compose schemas defined across multiple files.
22
+ */
23
+ type VardSchemaFragment<S extends VardSchema> = S & {
24
+ readonly __fragment: true;
25
+ };
26
+ /**
27
+ * Merges two VardSchema types, with B's keys overriding A on collision.
28
+ */
29
+ type MergeSchema<A extends VardSchema, B extends VardSchema> = Omit<A, keyof B> & B;
30
+ type InferSchema<T> = 0 extends 1 & T ? any : T extends VardField<infer U> ? U : T extends VardCollection<infer S> ? InferSchema<S>[] : T extends VardSchemaFragment<infer S> ? InferSchema<S> : T extends Record<string, any> ? {
31
+ [K in keyof T as K extends "__fragment" ? never : K]: InferSchema<T[K]>;
32
+ } : T;
33
+
34
+ type VardVariableType = "string" | "richtext" | "color" | "image" | "boolean" | "list";
35
+ type VardListItemSchema = Record<string, "string" | "richtext" | "color" | "image" | "boolean">;
36
+ type InferListItem<S extends VardListItemSchema> = {
37
+ [K in keyof S]: S[K] extends "string" ? string : S[K] extends "richtext" ? string : S[K] extends "color" ? string : S[K] extends "image" ? string : S[K] extends "boolean" ? boolean : never;
38
+ };
39
+ type VardRole = "owner" | "developer" | "member" | "viewer";
40
+ interface VardVariableDefinition<T = unknown> {
41
+ /** Dot-notation key, e.g. "hero.title" */
42
+ key: string;
43
+ /** Human-readable label shown in the client portal */
44
+ label: string;
45
+ type: VardVariableType;
46
+ /** The default value baked into the codebase */
47
+ defaultValue: T;
48
+ /** Minimum role required to edit this variable. Defaults to "member". */
49
+ editableBy: VardRole;
50
+ /** Optional description shown as a hint in the client portal */
51
+ description?: string;
52
+ /** For list variables — the schema of each item */
53
+ listItemSchema?: VardListItemSchema;
54
+ /** Optional grouping for the dashboard UI */
55
+ group?: string;
56
+ /** Indicates this is a reusable content pool/collection */
57
+ isCollection?: boolean;
58
+ }
59
+ interface VardStore {
60
+ /** Returns a stored value for the given key, or undefined if not set */
61
+ get(key: string): unknown;
62
+ /** Returns the full structured content object */
63
+ getStructured?(): any;
64
+ /** Ensures all values are loaded from the backend */
65
+ prefetch?(): Promise<void>;
66
+ }
67
+ interface VardOptions<S extends VardSchema = any> {
68
+ /**
69
+ * API Key for authentication. Read from VARD_API_KEY env var if not provided.
70
+ * This is the preferred way to configure the SDK as it's tied to your workspace.
71
+ */
72
+ apiKey?: string;
73
+ /**
74
+ * Optional content schema for type-safe data access and auto-syncing.
75
+ */
76
+ schema?: S;
77
+ /**
78
+ * VARD_API_KEY is unset (local dev without Vard).
79
+ */
80
+ store?: VardStore;
81
+ /**
82
+ * Enable verbose logging for requests and responses.
83
+ * Useful for debugging connection issues and verifying data flow.
84
+ */
85
+ debug?: boolean;
86
+ }
87
+ interface VardClient<S extends VardSchema = any> {
88
+ /**
89
+ * Define your content structure for type-safe data access and auto-syncing.
90
+ *
91
+ * @example
92
+ * const content = vard.define({
93
+ * hero: { title: v.string("Welcome") }
94
+ * });
95
+ */
96
+ define<NS extends VardSchema>(schema: NS): InferSchema<NS>;
97
+ /**
98
+ * Returns a type-safe object containing all variable values matching the schema.
99
+ */
100
+ get(): Promise<InferSchema<S>>;
101
+ /**
102
+ * Returns a new scoped client with the given schema fragment merged in.
103
+ * Shares the same underlying store and registry as the parent client.
104
+ * Use this to co-locate page-specific schema definitions with their pages.
105
+ *
106
+ * @example
107
+ * // app/therapists/schema.ts
108
+ * export const therapistSchema = v.schema({
109
+ * therapists: v.collection({ name: v.string() }),
110
+ * });
111
+ *
112
+ * // app/therapists/page.tsx
113
+ * const { therapists, global } = await vard.extend(therapistSchema).get();
114
+ */
115
+ extend<E extends VardSchema>(fragment: VardSchemaFragment<E>): VardClient<MergeSchema<S, E>>;
116
+ /**
117
+ * Access to global (project-wide) variables.
118
+ * e.g., vard.global.string("contact.email", "...")
119
+ */
120
+ global: VardGlobalClient;
121
+ /**
122
+ * Define a reusable content pool/collection.
123
+ */
124
+ collection<S extends VardListItemSchema>(key: string, schema: S, fallback: InferListItem<S>[], options?: Omit<VardVariableOptions, "type">): InferListItem<S>[];
125
+ /**
126
+ * A plain string variable. e.g. a hero headline, a CTA label.
127
+ *
128
+ * @param key Dot-notation identifier, unique within the workspace
129
+ * @param fallback Default value when no client value is stored
130
+ * @param options Optional label, description, permission
131
+ */
132
+ string(key: string, fallback: string, options?: VardVariableOptions): string;
133
+ /**
134
+ * A rich text (markdown) variable. Rendered as HTML at build time.
135
+ */
136
+ richtext(key: string, fallback: string, options?: VardVariableOptions): string;
137
+ /**
138
+ * A CSS color string (hex, hsl, rgb).
139
+ */
140
+ color(key: string, fallback: string, options?: VardVariableOptions): string;
141
+ /**
142
+ * A URL pointing to an uploaded asset (image, video).
143
+ */
144
+ image(key: string, fallback: string, options?: VardVariableOptions): string;
145
+ /**
146
+ * A boolean feature flag. e.g. show/hide a section.
147
+ */
148
+ boolean(key: string, fallback: boolean, options?: Omit<VardVariableOptions, "type">): boolean;
149
+ /**
150
+ * An ordered list of typed objects. e.g. team members, testimonials.
151
+ *
152
+ * @param schema Defines the shape of each list item
153
+ */
154
+ list<S extends VardListItemSchema>(key: string, schema: S, fallback: InferListItem<S>[], options?: Omit<VardVariableOptions, "type">): InferListItem<S>[];
155
+ /**
156
+ * Returns all registered variable definitions. Used by the CLI scanner
157
+ * and the build pipeline to sync definitions to the Vard API.
158
+ */
159
+ getDefinitions(): VardVariableDefinition[];
160
+ /**
161
+ * Access to the underlying store.
162
+ */
163
+ readonly store: VardStore;
164
+ }
165
+ interface VardGlobalClient {
166
+ string(key: string, fallback: string, options?: Omit<VardVariableOptions, "group">): string;
167
+ richtext(key: string, fallback: string, options?: Omit<VardVariableOptions, "group">): string;
168
+ color(key: string, fallback: string, options?: Omit<VardVariableOptions, "group">): string;
169
+ image(key: string, fallback: string, options?: Omit<VardVariableOptions, "group">): string;
170
+ boolean(key: string, fallback: boolean, options?: Omit<VardVariableOptions, "type" | "group">): boolean;
171
+ list<S extends VardListItemSchema>(key: string, schema: S, fallback: InferListItem<S>[], options?: Omit<VardVariableOptions, "type" | "group">): InferListItem<S>[];
172
+ }
173
+ interface VardVariableOptions {
174
+ label?: string;
175
+ description?: string;
176
+ editableBy?: VardRole;
177
+ group?: string;
178
+ }
2
179
 
3
180
  /**
4
181
  * @vard/sdk — Next.js adapter
@@ -54,7 +231,7 @@ declare function createVardNextAdapter(options?: VardNextAdapterOptions): VardSt
54
231
  * import { createVardNext } from "@vard/sdk/next"
55
232
  * export const vard = createVardNext({ revalidate: 60 })
56
233
  */
57
- declare function createVardNext(options?: VardNextAdapterOptions & VardOptions): VardClient;
234
+ declare function createVardNext<S extends VardSchema = any>(options?: VardNextAdapterOptions & VardOptions<S>): VardClient<S>;
58
235
  declare function prefetchVardValues(target: {
59
236
  prefetch(): Promise<void>;
60
237
  } | VardClient): Promise<void>;