@vard-app/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # @vard/sdk
2
+
3
+ The Vard SDK lets developers annotate variables in their Next.js site so clients can edit them through the Vard portal — without touching code.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @vard-app/sdk
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ### 1. Create your vard client
14
+
15
+ ```ts
16
+ // lib/vard.ts
17
+ import { createVard } from "@vard-app/sdk"
18
+ import { createVardNextAdapter } from "@vard-app/sdk/next"
19
+
20
+ export const vard = createVard({
21
+ workspaceId: process.env.VARD_WORKSPACE_ID,
22
+ store: createVardNextAdapter(),
23
+ })
24
+ ```
25
+
26
+ ### 2. Use variables anywhere in your site
27
+
28
+ ```tsx
29
+ // app/page.tsx
30
+ import { vard } from "@/lib/vard"
31
+
32
+ export default function HomePage() {
33
+ const heroTitle = vard.string("hero.title", "Welcome to our site")
34
+ const heroCopy = vard.richtext("hero.copy", "We build great things.")
35
+ const primaryColor = vard.color("theme.primary", "#2563eb")
36
+ const heroImage = vard.image("hero.image", "/default-hero.jpg")
37
+ const showBanner = vard.boolean("banner.show", false)
38
+
39
+ const team = vard.list(
40
+ "team.members",
41
+ { name: "string", role: "string", photo: "image" },
42
+ [{ name: "Jane Doe", role: "Founder", photo: "/jane.jpg" }],
43
+ { label: "Team Members" }
44
+ )
45
+
46
+ return (
47
+ <main style={{ "--primary": primaryColor } as React.CSSProperties}>
48
+ {showBanner && <Banner />}
49
+ <h1>{heroTitle}</h1>
50
+ <p dangerouslySetInnerHTML={{ __html: heroCopy }} />
51
+ {team.map((member) => (
52
+ <TeamCard key={member.name} {...member} />
53
+ ))}
54
+ </main>
55
+ )
56
+ }
57
+ ```
58
+
59
+ ### 3. Prefetch values in your layout (App Router)
60
+
61
+ ```tsx
62
+ // app/layout.tsx
63
+ import { createVardNextAdapter, prefetchVardValues } from "@vard/sdk/next"
64
+ import { vard } from "@/lib/vard"
65
+
66
+ export default async function RootLayout({ children }: { children: React.ReactNode }) {
67
+ await prefetchVardValues(vard.store as ReturnType<typeof createVardNextAdapter>)
68
+ return <html><body>{children}</body></html>
69
+ }
70
+ ```
71
+
72
+ ## Variable types
73
+
74
+ | Method | Type | Client UI |
75
+ |---|---|---|
76
+ | `vard.string()` | Plain text | Text input |
77
+ | `vard.richtext()` | Markdown | Rich text editor |
78
+ | `vard.color()` | CSS color string | Color picker |
79
+ | `vard.image()` | Asset URL | Image uploader |
80
+ | `vard.boolean()` | `true` / `false` | Toggle switch |
81
+ | `vard.list()` | Array of typed objects | Repeater |
82
+
83
+ ## Permissions
84
+
85
+ Each variable can restrict which role can edit it:
86
+
87
+ ```ts
88
+ vard.color("theme.primary", "#2563eb", {
89
+ label: "Brand Color",
90
+ editableBy: "owner", // only owners can change this
91
+ })
92
+ ```
93
+
94
+ Roles: `owner` > `developer` > `member` > `viewer`
95
+
96
+ ## Local development
97
+
98
+ If `VARD_WORKSPACE_ID` is not set, the SDK returns default values for every variable — your site works perfectly without a Vard account during development.
99
+
100
+ ## Environment variables
101
+
102
+ | Variable | Description |
103
+ |---|---|
104
+ | `VARD_WORKSPACE_ID` | Your Vard workspace ID |
@@ -0,0 +1,19 @@
1
+ import { V as VardOptions, a as VardClient } from './types-DLM7i_Qr.mjs';
2
+ export { I as InferListItem, b as VardListItemSchema, c as VardRole, d as VardStore, e as VardVariableDefinition, f as VardVariableOptions, g as VardVariableType } from './types-DLM7i_Qr.mjs';
3
+
4
+ /**
5
+ * Creates a Vard client instance. Call this once at the top of your site
6
+ * (e.g. in `lib/vard.ts`) and export the result.
7
+ *
8
+ * @example
9
+ * // lib/vard.ts
10
+ * import { createVard } from "@vard/sdk"
11
+ * export const vard = createVard()
12
+ *
13
+ * // app/page.tsx
14
+ * import { vard } from "@/lib/vard"
15
+ * const title = vard.string("hero.title", "Hello, world")
16
+ */
17
+ declare function createVard(options?: VardOptions): VardClient;
18
+
19
+ export { VardClient, VardOptions, createVard };
@@ -0,0 +1,19 @@
1
+ import { V as VardOptions, a as VardClient } from './types-DLM7i_Qr.js';
2
+ export { I as InferListItem, b as VardListItemSchema, c as VardRole, d as VardStore, e as VardVariableDefinition, f as VardVariableOptions, g as VardVariableType } from './types-DLM7i_Qr.js';
3
+
4
+ /**
5
+ * Creates a Vard client instance. Call this once at the top of your site
6
+ * (e.g. in `lib/vard.ts`) and export the result.
7
+ *
8
+ * @example
9
+ * // lib/vard.ts
10
+ * import { createVard } from "@vard/sdk"
11
+ * export const vard = createVard()
12
+ *
13
+ * // app/page.tsx
14
+ * import { vard } from "@/lib/vard"
15
+ * const title = vard.string("hero.title", "Hello, world")
16
+ */
17
+ declare function createVard(options?: VardOptions): VardClient;
18
+
19
+ export { VardClient, VardOptions, createVard };
package/dist/index.js ADDED
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ createVard: () => createVard
24
+ });
25
+ module.exports = __toCommonJS(src_exports);
26
+
27
+ // src/client.ts
28
+ var noopStore = {
29
+ get: () => void 0
30
+ };
31
+ function createVard(options = {}) {
32
+ const store = options.store ?? noopStore;
33
+ const registry = [];
34
+ function register(def) {
35
+ if (!registry.find((d) => d.key === def.key)) {
36
+ registry.push(def);
37
+ }
38
+ const stored = store.get(def.key);
39
+ if (stored !== void 0 && stored !== null) {
40
+ return stored;
41
+ }
42
+ return def.defaultValue;
43
+ }
44
+ const client = {
45
+ string(key, fallback, opts = {}) {
46
+ return register({
47
+ key,
48
+ label: opts.label ?? labelFromKey(key),
49
+ description: opts.description,
50
+ type: "string",
51
+ defaultValue: fallback,
52
+ editableBy: opts.editableBy ?? "member"
53
+ });
54
+ },
55
+ richtext(key, fallback, opts = {}) {
56
+ return register({
57
+ key,
58
+ label: opts.label ?? labelFromKey(key),
59
+ description: opts.description,
60
+ type: "richtext",
61
+ defaultValue: fallback,
62
+ editableBy: opts.editableBy ?? "member"
63
+ });
64
+ },
65
+ color(key, fallback, opts = {}) {
66
+ return register({
67
+ key,
68
+ label: opts.label ?? labelFromKey(key),
69
+ description: opts.description,
70
+ type: "color",
71
+ defaultValue: fallback,
72
+ editableBy: opts.editableBy ?? "member"
73
+ });
74
+ },
75
+ image(key, fallback, opts = {}) {
76
+ return register({
77
+ key,
78
+ label: opts.label ?? labelFromKey(key),
79
+ description: opts.description,
80
+ type: "image",
81
+ defaultValue: fallback,
82
+ editableBy: opts.editableBy ?? "member"
83
+ });
84
+ },
85
+ boolean(key, fallback, opts = {}) {
86
+ return register({
87
+ key,
88
+ label: opts.label ?? labelFromKey(key),
89
+ description: opts.description,
90
+ type: "boolean",
91
+ defaultValue: fallback,
92
+ editableBy: opts.editableBy ?? "member"
93
+ });
94
+ },
95
+ list(key, schema, fallback, opts = {}) {
96
+ return register({
97
+ key,
98
+ label: opts.label ?? labelFromKey(key),
99
+ description: opts.description,
100
+ type: "list",
101
+ defaultValue: fallback,
102
+ editableBy: opts.editableBy ?? "member",
103
+ listItemSchema: schema
104
+ });
105
+ },
106
+ getDefinitions() {
107
+ return [...registry];
108
+ }
109
+ };
110
+ return client;
111
+ }
112
+ function labelFromKey(key) {
113
+ const lastSegment = key.split(".").pop() ?? key;
114
+ return lastSegment.replace(/([A-Z])/g, " $1").replace(/^./, (c) => c.toUpperCase()).trim();
115
+ }
116
+ // Annotate the CommonJS export names for ESM import in node:
117
+ 0 && (module.exports = {
118
+ createVard
119
+ });
120
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/client.ts"],"sourcesContent":["// Public entrypoint for @vard/sdk\nexport { createVard } from \"./client\";\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 {\n VardClient,\n VardOptions,\n VardStore,\n VardVariableDefinition,\n VardVariableOptions,\n VardListItemSchema,\n InferListItem,\n VardRole,\n} from \"./types\";\n\n// ─────────────────────────────────────────────\n// No-op store (used in local dev when no workspaceId is set)\n// ─────────────────────────────────────────────\n\nconst noopStore: VardStore = {\n get: () => undefined,\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 *\n * @example\n * // lib/vard.ts\n * import { createVard } from \"@vard/sdk\"\n * export const vard = createVard()\n *\n * // app/page.tsx\n * import { vard } from \"@/lib/vard\"\n * const title = vard.string(\"hero.title\", \"Hello, world\")\n */\nexport function createVard(options: VardOptions = {}): VardClient {\n const store: VardStore = options.store ?? 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 // Avoid double-registering the same key (e.g. in hot-reload scenarios)\n if (!registry.find((d) => d.key === def.key)) {\n registry.push(def as VardVariableDefinition);\n }\n\n // Resolve value: stored client value takes precedence over the default\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 const client: VardClient = {\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 });\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 });\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 });\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 });\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 });\n },\n\n list<S extends VardListItemSchema>(\n key: string,\n schema: S,\n fallback: InferListItem<S>[],\n opts: VardVariableOptions = {}\n ): InferListItem<S>[] {\n return register<InferListItem<S>[]>({\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 });\n },\n\n getDefinitions() {\n return [...registry];\n },\n };\n\n return client;\n}\n\n// ─────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────\n\n/**\n * Converts a dot-notation key to a human-readable label.\n * e.g. \"hero.primaryTitle\" → \"Hero Primary Title\"\n */\nfunction labelFromKey(key: string): string {\n const lastSegment = key.split(\".\").pop() ?? key;\n // Split on camelCase boundaries and capitalise\n return lastSegment\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (c) => c.toUpperCase())\n .trim();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACeA,IAAM,YAAuB;AAAA,EAC3B,KAAK,MAAM;AACb;AAmBO,SAAS,WAAW,UAAuB,CAAC,GAAe;AAChE,QAAM,QAAmB,QAAQ,SAAS;AAG1C,QAAM,WAAqC,CAAC;AAE5C,WAAS,SAAY,KAAmC;AAEtD,QAAI,CAAC,SAAS,KAAK,CAAC,MAAM,EAAE,QAAQ,IAAI,GAAG,GAAG;AAC5C,eAAS,KAAK,GAA6B;AAAA,IAC7C;AAGA,UAAM,SAAS,MAAM,IAAI,IAAI,GAAG;AAChC,QAAI,WAAW,UAAa,WAAW,MAAM;AAC3C,aAAO;AAAA,IACT;AAEA,WAAO,IAAI;AAAA,EACb;AAEA,QAAM,SAAqB;AAAA,IACzB,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,MACjC,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,MACjC,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,MACjC,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,MACjC,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,MAC/C,CAAC;AAAA,IACH;AAAA,IAEA,KACE,KACA,QACA,UACA,OAA4B,CAAC,GACT;AACpB,aAAO,SAA6B;AAAA,QAClC;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,MAClB,CAAC;AAAA,IACH;AAAA,IAEA,iBAAiB;AACf,aAAO,CAAC,GAAG,QAAQ;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AACT;AAUA,SAAS,aAAa,KAAqB;AACzC,QAAM,cAAc,IAAI,MAAM,GAAG,EAAE,IAAI,KAAK;AAE5C,SAAO,YACJ,QAAQ,YAAY,KAAK,EACzB,QAAQ,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EACpC,KAAK;AACV;","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,93 @@
1
+ // src/client.ts
2
+ var noopStore = {
3
+ get: () => void 0
4
+ };
5
+ function createVard(options = {}) {
6
+ const store = options.store ?? noopStore;
7
+ const registry = [];
8
+ function register(def) {
9
+ if (!registry.find((d) => d.key === def.key)) {
10
+ registry.push(def);
11
+ }
12
+ const stored = store.get(def.key);
13
+ if (stored !== void 0 && stored !== null) {
14
+ return stored;
15
+ }
16
+ return def.defaultValue;
17
+ }
18
+ const client = {
19
+ string(key, fallback, opts = {}) {
20
+ return register({
21
+ key,
22
+ label: opts.label ?? labelFromKey(key),
23
+ description: opts.description,
24
+ type: "string",
25
+ defaultValue: fallback,
26
+ editableBy: opts.editableBy ?? "member"
27
+ });
28
+ },
29
+ richtext(key, fallback, opts = {}) {
30
+ return register({
31
+ key,
32
+ label: opts.label ?? labelFromKey(key),
33
+ description: opts.description,
34
+ type: "richtext",
35
+ defaultValue: fallback,
36
+ editableBy: opts.editableBy ?? "member"
37
+ });
38
+ },
39
+ color(key, fallback, opts = {}) {
40
+ return register({
41
+ key,
42
+ label: opts.label ?? labelFromKey(key),
43
+ description: opts.description,
44
+ type: "color",
45
+ defaultValue: fallback,
46
+ editableBy: opts.editableBy ?? "member"
47
+ });
48
+ },
49
+ image(key, fallback, opts = {}) {
50
+ return register({
51
+ key,
52
+ label: opts.label ?? labelFromKey(key),
53
+ description: opts.description,
54
+ type: "image",
55
+ defaultValue: fallback,
56
+ editableBy: opts.editableBy ?? "member"
57
+ });
58
+ },
59
+ boolean(key, fallback, opts = {}) {
60
+ return register({
61
+ key,
62
+ label: opts.label ?? labelFromKey(key),
63
+ description: opts.description,
64
+ type: "boolean",
65
+ defaultValue: fallback,
66
+ editableBy: opts.editableBy ?? "member"
67
+ });
68
+ },
69
+ list(key, schema, fallback, opts = {}) {
70
+ return register({
71
+ key,
72
+ label: opts.label ?? labelFromKey(key),
73
+ description: opts.description,
74
+ type: "list",
75
+ defaultValue: fallback,
76
+ editableBy: opts.editableBy ?? "member",
77
+ listItemSchema: schema
78
+ });
79
+ },
80
+ getDefinitions() {
81
+ return [...registry];
82
+ }
83
+ };
84
+ return client;
85
+ }
86
+ function labelFromKey(key) {
87
+ const lastSegment = key.split(".").pop() ?? key;
88
+ return lastSegment.replace(/([A-Z])/g, " $1").replace(/^./, (c) => c.toUpperCase()).trim();
89
+ }
90
+ export {
91
+ createVard
92
+ };
93
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type {\n VardClient,\n VardOptions,\n VardStore,\n VardVariableDefinition,\n VardVariableOptions,\n VardListItemSchema,\n InferListItem,\n VardRole,\n} from \"./types\";\n\n// ─────────────────────────────────────────────\n// No-op store (used in local dev when no workspaceId is set)\n// ─────────────────────────────────────────────\n\nconst noopStore: VardStore = {\n get: () => undefined,\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 *\n * @example\n * // lib/vard.ts\n * import { createVard } from \"@vard/sdk\"\n * export const vard = createVard()\n *\n * // app/page.tsx\n * import { vard } from \"@/lib/vard\"\n * const title = vard.string(\"hero.title\", \"Hello, world\")\n */\nexport function createVard(options: VardOptions = {}): VardClient {\n const store: VardStore = options.store ?? 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 // Avoid double-registering the same key (e.g. in hot-reload scenarios)\n if (!registry.find((d) => d.key === def.key)) {\n registry.push(def as VardVariableDefinition);\n }\n\n // Resolve value: stored client value takes precedence over the default\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 const client: VardClient = {\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 });\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 });\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 });\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 });\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 });\n },\n\n list<S extends VardListItemSchema>(\n key: string,\n schema: S,\n fallback: InferListItem<S>[],\n opts: VardVariableOptions = {}\n ): InferListItem<S>[] {\n return register<InferListItem<S>[]>({\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 });\n },\n\n getDefinitions() {\n return [...registry];\n },\n };\n\n return client;\n}\n\n// ─────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────\n\n/**\n * Converts a dot-notation key to a human-readable label.\n * e.g. \"hero.primaryTitle\" → \"Hero Primary Title\"\n */\nfunction labelFromKey(key: string): string {\n const lastSegment = key.split(\".\").pop() ?? key;\n // Split on camelCase boundaries and capitalise\n return lastSegment\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (c) => c.toUpperCase())\n .trim();\n}\n"],"mappings":";AAeA,IAAM,YAAuB;AAAA,EAC3B,KAAK,MAAM;AACb;AAmBO,SAAS,WAAW,UAAuB,CAAC,GAAe;AAChE,QAAM,QAAmB,QAAQ,SAAS;AAG1C,QAAM,WAAqC,CAAC;AAE5C,WAAS,SAAY,KAAmC;AAEtD,QAAI,CAAC,SAAS,KAAK,CAAC,MAAM,EAAE,QAAQ,IAAI,GAAG,GAAG;AAC5C,eAAS,KAAK,GAA6B;AAAA,IAC7C;AAGA,UAAM,SAAS,MAAM,IAAI,IAAI,GAAG;AAChC,QAAI,WAAW,UAAa,WAAW,MAAM;AAC3C,aAAO;AAAA,IACT;AAEA,WAAO,IAAI;AAAA,EACb;AAEA,QAAM,SAAqB;AAAA,IACzB,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,MACjC,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,MACjC,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,MACjC,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,MACjC,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,MAC/C,CAAC;AAAA,IACH;AAAA,IAEA,KACE,KACA,QACA,UACA,OAA4B,CAAC,GACT;AACpB,aAAO,SAA6B;AAAA,QAClC;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,MAClB,CAAC;AAAA,IACH;AAAA,IAEA,iBAAiB;AACf,aAAO,CAAC,GAAG,QAAQ;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AACT;AAUA,SAAS,aAAa,KAAqB;AACzC,QAAM,cAAc,IAAI,MAAM,GAAG,EAAE,IAAI,KAAK;AAE5C,SAAO,YACJ,QAAQ,YAAY,KAAK,EACzB,QAAQ,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EACpC,KAAK;AACV;","names":[]}
@@ -0,0 +1,78 @@
1
+ import { d as VardStore } from './types-DLM7i_Qr.mjs';
2
+
3
+ /**
4
+ * @vard/sdk — Next.js adapter
5
+ *
6
+ * This module provides a VardStore implementation that reads variable values
7
+ * from the Vard API at request time (App Router) or build time (static export).
8
+ *
9
+ * Usage in your Next.js site:
10
+ *
11
+ * // lib/vard.ts
12
+ * import { createVardNextAdapter } from "@vard/sdk/next"
13
+ * import { createVard } from "@vard/sdk"
14
+ *
15
+ * export const vard = createVard({
16
+ * workspaceId: process.env.VARD_WORKSPACE_ID,
17
+ * store: createVardNextAdapter(),
18
+ * })
19
+ *
20
+ * The adapter fetches variable values from the Vard API:
21
+ * GET https://api.vard.app/v1/workspaces/{workspaceId}/variables
22
+ *
23
+ * In local development (no VARD_WORKSPACE_ID set) it silently falls back
24
+ * to default values so your site works without any Vard account.
25
+ */
26
+
27
+ interface VardNextAdapterOptions {
28
+ /**
29
+ * Base URL of the Vard API. Defaults to https://api.vard.app
30
+ */
31
+ apiBase?: string;
32
+ /**
33
+ * Workspace ID. Falls back to process.env.VARD_WORKSPACE_ID.
34
+ */
35
+ workspaceId?: string;
36
+ /**
37
+ * API Key for authentication. Falls back to process.env.VARD_API_KEY.
38
+ */
39
+ apiKey?: string;
40
+ /**
41
+ * Next.js fetch cache strategy. Defaults to "force-cache" (SSG-friendly).
42
+ * Use "no-store" for fully dynamic pages.
43
+ */
44
+ cache?: RequestCache;
45
+ /**
46
+ * Next.js ISR revalidation interval in seconds.
47
+ * Only applies when cache is "force-cache".
48
+ */
49
+ revalidate?: number;
50
+ }
51
+ /**
52
+ * Creates a VardStore that fetches live variable values from the Vard API.
53
+ * Designed for use inside Next.js App Router (server components, server actions).
54
+ *
55
+ * Values are fetched once per request and cached in a simple Map.
56
+ * In local dev with no workspaceId, returns undefined for every key (defaults take over).
57
+ */
58
+ declare function createVardNextAdapter(options?: VardNextAdapterOptions): VardStore;
59
+ /**
60
+ * A convenience wrapper that creates a Vard client pre-loaded with live values.
61
+ * Call this once in your Next.js layout before rendering any server component
62
+ * that uses vard variables.
63
+ *
64
+ * @example
65
+ * // app/layout.tsx
66
+ * import { prefetchVardValues } from "@vard/sdk/next"
67
+ * import { vard } from "@/lib/vard"
68
+ *
69
+ * export default async function RootLayout({ children }) {
70
+ * await prefetchVardValues(vard)
71
+ * return <html>...</html>
72
+ * }
73
+ */
74
+ declare function prefetchVardValues(adapter: {
75
+ prefetch(): Promise<void>;
76
+ }): Promise<void>;
77
+
78
+ export { type VardNextAdapterOptions, createVardNextAdapter, prefetchVardValues };
package/dist/next.d.ts ADDED
@@ -0,0 +1,78 @@
1
+ import { d as VardStore } from './types-DLM7i_Qr.js';
2
+
3
+ /**
4
+ * @vard/sdk — Next.js adapter
5
+ *
6
+ * This module provides a VardStore implementation that reads variable values
7
+ * from the Vard API at request time (App Router) or build time (static export).
8
+ *
9
+ * Usage in your Next.js site:
10
+ *
11
+ * // lib/vard.ts
12
+ * import { createVardNextAdapter } from "@vard/sdk/next"
13
+ * import { createVard } from "@vard/sdk"
14
+ *
15
+ * export const vard = createVard({
16
+ * workspaceId: process.env.VARD_WORKSPACE_ID,
17
+ * store: createVardNextAdapter(),
18
+ * })
19
+ *
20
+ * The adapter fetches variable values from the Vard API:
21
+ * GET https://api.vard.app/v1/workspaces/{workspaceId}/variables
22
+ *
23
+ * In local development (no VARD_WORKSPACE_ID set) it silently falls back
24
+ * to default values so your site works without any Vard account.
25
+ */
26
+
27
+ interface VardNextAdapterOptions {
28
+ /**
29
+ * Base URL of the Vard API. Defaults to https://api.vard.app
30
+ */
31
+ apiBase?: string;
32
+ /**
33
+ * Workspace ID. Falls back to process.env.VARD_WORKSPACE_ID.
34
+ */
35
+ workspaceId?: string;
36
+ /**
37
+ * API Key for authentication. Falls back to process.env.VARD_API_KEY.
38
+ */
39
+ apiKey?: string;
40
+ /**
41
+ * Next.js fetch cache strategy. Defaults to "force-cache" (SSG-friendly).
42
+ * Use "no-store" for fully dynamic pages.
43
+ */
44
+ cache?: RequestCache;
45
+ /**
46
+ * Next.js ISR revalidation interval in seconds.
47
+ * Only applies when cache is "force-cache".
48
+ */
49
+ revalidate?: number;
50
+ }
51
+ /**
52
+ * Creates a VardStore that fetches live variable values from the Vard API.
53
+ * Designed for use inside Next.js App Router (server components, server actions).
54
+ *
55
+ * Values are fetched once per request and cached in a simple Map.
56
+ * In local dev with no workspaceId, returns undefined for every key (defaults take over).
57
+ */
58
+ declare function createVardNextAdapter(options?: VardNextAdapterOptions): VardStore;
59
+ /**
60
+ * A convenience wrapper that creates a Vard client pre-loaded with live values.
61
+ * Call this once in your Next.js layout before rendering any server component
62
+ * that uses vard variables.
63
+ *
64
+ * @example
65
+ * // app/layout.tsx
66
+ * import { prefetchVardValues } from "@vard/sdk/next"
67
+ * import { vard } from "@/lib/vard"
68
+ *
69
+ * export default async function RootLayout({ children }) {
70
+ * await prefetchVardValues(vard)
71
+ * return <html>...</html>
72
+ * }
73
+ */
74
+ declare function prefetchVardValues(adapter: {
75
+ prefetch(): Promise<void>;
76
+ }): Promise<void>;
77
+
78
+ export { type VardNextAdapterOptions, createVardNextAdapter, prefetchVardValues };
package/dist/next.js ADDED
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/next.ts
21
+ var next_exports = {};
22
+ __export(next_exports, {
23
+ createVardNextAdapter: () => createVardNextAdapter,
24
+ prefetchVardValues: () => prefetchVardValues
25
+ });
26
+ module.exports = __toCommonJS(next_exports);
27
+ function createVardNextAdapter(options = {}) {
28
+ const {
29
+ apiBase = "https://api.vard.app",
30
+ workspaceId = process.env.VARD_WORKSPACE_ID,
31
+ apiKey = process.env.VARD_API_KEY,
32
+ cache = "force-cache",
33
+ revalidate = 60
34
+ } = options;
35
+ let resolvedValues = null;
36
+ let fetchPromise = null;
37
+ async function fetchValues() {
38
+ if (!apiKey && !workspaceId) {
39
+ return /* @__PURE__ */ new Map();
40
+ }
41
+ const url = apiKey ? `${apiBase}/api/content/variables` : `${apiBase}/v1/workspaces/${workspaceId}/variables`;
42
+ try {
43
+ const res = await fetch(url, {
44
+ cache,
45
+ headers: {
46
+ ...apiKey ? { "X-Vard-API-Key": apiKey } : {}
47
+ },
48
+ // Next.js specific: revalidation hint
49
+ ...revalidate !== void 0 && cache === "force-cache" ? { next: { revalidate } } : {}
50
+ });
51
+ if (!res.ok) {
52
+ console.warn(
53
+ `[vard] Failed to fetch variables: ${res.status}`
54
+ );
55
+ return /* @__PURE__ */ new Map();
56
+ }
57
+ const data = await res.json();
58
+ return new Map(data.map((v) => [v.key, v.value]));
59
+ } catch (err) {
60
+ console.warn("[vard] Error fetching variable values:", err);
61
+ return /* @__PURE__ */ new Map();
62
+ }
63
+ }
64
+ return {
65
+ get(key) {
66
+ return resolvedValues?.get(key);
67
+ },
68
+ // Extended method — not on base VardStore interface, but available
69
+ // for Next.js users who import from @vard/sdk/next
70
+ async prefetch() {
71
+ if (resolvedValues) return;
72
+ if (!fetchPromise) {
73
+ fetchPromise = fetchValues();
74
+ }
75
+ resolvedValues = await fetchPromise;
76
+ }
77
+ };
78
+ }
79
+ async function prefetchVardValues(adapter) {
80
+ await adapter.prefetch();
81
+ }
82
+ // Annotate the CommonJS export names for ESM import in node:
83
+ 0 && (module.exports = {
84
+ createVardNextAdapter,
85
+ prefetchVardValues
86
+ });
87
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/next.ts"],"sourcesContent":["/**\n * @vard/sdk — Next.js adapter\n *\n * This module provides a VardStore implementation that reads variable values\n * from the Vard API at request time (App Router) or build time (static export).\n *\n * Usage in your Next.js site:\n *\n * // lib/vard.ts\n * import { createVardNextAdapter } from \"@vard/sdk/next\"\n * import { createVard } from \"@vard/sdk\"\n *\n * export const vard = createVard({\n * workspaceId: process.env.VARD_WORKSPACE_ID,\n * store: createVardNextAdapter(),\n * })\n *\n * The adapter fetches variable values from the Vard API:\n * GET https://api.vard.app/v1/workspaces/{workspaceId}/variables\n *\n * In local development (no VARD_WORKSPACE_ID set) it silently falls back\n * to default values so your site works without any Vard account.\n */\n\nimport type { VardStore } from \"./types\";\n\nexport interface VardNextAdapterOptions {\n /**\n * Base URL of the Vard API. Defaults to https://api.vard.app\n */\n apiBase?: string;\n\n /**\n * Workspace ID. Falls back to process.env.VARD_WORKSPACE_ID.\n */\n workspaceId?: string;\n\n /**\n * API Key for authentication. Falls back to process.env.VARD_API_KEY.\n */\n apiKey?: string;\n\n /**\n * Next.js fetch cache strategy. Defaults to \"force-cache\" (SSG-friendly).\n * Use \"no-store\" for fully dynamic pages.\n */\n cache?: RequestCache;\n\n /**\n * Next.js ISR revalidation interval in seconds.\n * Only applies when cache is \"force-cache\".\n */\n revalidate?: number;\n}\n\n/**\n * Creates a VardStore that fetches live variable values from the Vard API.\n * Designed for use inside Next.js App Router (server components, server actions).\n *\n * Values are fetched once per request and cached in a simple Map.\n * In local dev with no workspaceId, returns undefined for every key (defaults take over).\n */\nexport function createVardNextAdapter(\n options: VardNextAdapterOptions = {}\n): VardStore {\n const {\n apiBase = \"https://api.vard.app\",\n workspaceId = process.env.VARD_WORKSPACE_ID,\n apiKey = process.env.VARD_API_KEY,\n cache = \"force-cache\",\n revalidate = 60,\n } = options;\n\n // In-memory cache per module instance (one Node.js process = one workspace)\n let resolvedValues: Map<string, unknown> | null = null;\n let fetchPromise: Promise<Map<string, unknown>> | null = null;\n\n async function fetchValues(): Promise<Map<string, unknown>> {\n if (!apiKey && !workspaceId) {\n return new Map();\n }\n\n // New format uses API Key and points to a generic content endpoint\n // Old format uses workspaceId and points to a workspace-specific endpoint\n const url = apiKey \n ? `${apiBase}/api/content/variables`\n : `${apiBase}/v1/workspaces/${workspaceId}/variables`;\n\n try {\n const res = await fetch(url, {\n cache,\n headers: {\n ...(apiKey ? { \"X-Vard-API-Key\": apiKey } : {}),\n },\n // Next.js specific: revalidation hint\n ...(revalidate !== undefined && cache === \"force-cache\"\n ? { next: { revalidate } }\n : {}),\n });\n\n if (!res.ok) {\n console.warn(\n `[vard] Failed to fetch variables: ${res.status}`\n );\n return new Map();\n }\n\n const data = (await res.json()) as { key: string; value: unknown }[];\n return new Map(data.map((v) => [v.key, v.value]));\n } catch (err) {\n console.warn(\"[vard] Error fetching variable values:\", err);\n return new Map();\n }\n }\n\n return {\n get(key: string): unknown {\n // Synchronous path — values must have been pre-fetched.\n // In Next.js App Router, call vard.prefetch() in your layout/page\n // before rendering, or use the async helper below.\n return resolvedValues?.get(key);\n },\n\n // Extended method — not on base VardStore interface, but available\n // for Next.js users who import from @vard/sdk/next\n async prefetch(): Promise<void> {\n if (resolvedValues) return;\n if (!fetchPromise) {\n fetchPromise = fetchValues();\n }\n resolvedValues = await fetchPromise;\n },\n } as VardStore & { prefetch(): Promise<void> };\n}\n\n/**\n * A convenience wrapper that creates a Vard client pre-loaded with live values.\n * Call this once in your Next.js layout before rendering any server component\n * that uses vard variables.\n *\n * @example\n * // app/layout.tsx\n * import { prefetchVardValues } from \"@vard/sdk/next\"\n * import { vard } from \"@/lib/vard\"\n *\n * export default async function RootLayout({ children }) {\n * await prefetchVardValues(vard)\n * return <html>...</html>\n * }\n */\nexport async function prefetchVardValues(\n adapter: { prefetch(): Promise<void> }\n): Promise<void> {\n await adapter.prefetch();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8DO,SAAS,sBACd,UAAkC,CAAC,GACxB;AACX,QAAM;AAAA,IACJ,UAAU;AAAA,IACV,cAAc,QAAQ,IAAI;AAAA,IAC1B,SAAS,QAAQ,IAAI;AAAA,IACrB,QAAQ;AAAA,IACR,aAAa;AAAA,EACf,IAAI;AAGJ,MAAI,iBAA8C;AAClD,MAAI,eAAqD;AAEzD,iBAAe,cAA6C;AAC1D,QAAI,CAAC,UAAU,CAAC,aAAa;AAC3B,aAAO,oBAAI,IAAI;AAAA,IACjB;AAIA,UAAM,MAAM,SACR,GAAG,OAAO,2BACV,GAAG,OAAO,kBAAkB,WAAW;AAE3C,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,KAAK;AAAA,QAC3B;AAAA,QACA,SAAS;AAAA,UACP,GAAI,SAAS,EAAE,kBAAkB,OAAO,IAAI,CAAC;AAAA,QAC/C;AAAA;AAAA,QAEA,GAAI,eAAe,UAAa,UAAU,gBACtC,EAAE,MAAM,EAAE,WAAW,EAAE,IACvB,CAAC;AAAA,MACP,CAAC;AAED,UAAI,CAAC,IAAI,IAAI;AACX,gBAAQ;AAAA,UACN,qCAAqC,IAAI,MAAM;AAAA,QACjD;AACA,eAAO,oBAAI,IAAI;AAAA,MACjB;AAEA,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,aAAO,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAAA,IAClD,SAAS,KAAK;AACZ,cAAQ,KAAK,0CAA0C,GAAG;AAC1D,aAAO,oBAAI,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,IAAI,KAAsB;AAIxB,aAAO,gBAAgB,IAAI,GAAG;AAAA,IAChC;AAAA;AAAA;AAAA,IAIA,MAAM,WAA0B;AAC9B,UAAI,eAAgB;AACpB,UAAI,CAAC,cAAc;AACjB,uBAAe,YAAY;AAAA,MAC7B;AACA,uBAAiB,MAAM;AAAA,IACzB;AAAA,EACF;AACF;AAiBA,eAAsB,mBACpB,SACe;AACf,QAAM,QAAQ,SAAS;AACzB;","names":[]}
package/dist/next.mjs ADDED
@@ -0,0 +1,61 @@
1
+ // src/next.ts
2
+ function createVardNextAdapter(options = {}) {
3
+ const {
4
+ apiBase = "https://api.vard.app",
5
+ workspaceId = process.env.VARD_WORKSPACE_ID,
6
+ apiKey = process.env.VARD_API_KEY,
7
+ cache = "force-cache",
8
+ revalidate = 60
9
+ } = options;
10
+ let resolvedValues = null;
11
+ let fetchPromise = null;
12
+ async function fetchValues() {
13
+ if (!apiKey && !workspaceId) {
14
+ return /* @__PURE__ */ new Map();
15
+ }
16
+ const url = apiKey ? `${apiBase}/api/content/variables` : `${apiBase}/v1/workspaces/${workspaceId}/variables`;
17
+ try {
18
+ const res = await fetch(url, {
19
+ cache,
20
+ headers: {
21
+ ...apiKey ? { "X-Vard-API-Key": apiKey } : {}
22
+ },
23
+ // Next.js specific: revalidation hint
24
+ ...revalidate !== void 0 && cache === "force-cache" ? { next: { revalidate } } : {}
25
+ });
26
+ if (!res.ok) {
27
+ console.warn(
28
+ `[vard] Failed to fetch variables: ${res.status}`
29
+ );
30
+ return /* @__PURE__ */ new Map();
31
+ }
32
+ const data = await res.json();
33
+ return new Map(data.map((v) => [v.key, v.value]));
34
+ } catch (err) {
35
+ console.warn("[vard] Error fetching variable values:", err);
36
+ return /* @__PURE__ */ new Map();
37
+ }
38
+ }
39
+ return {
40
+ get(key) {
41
+ return resolvedValues?.get(key);
42
+ },
43
+ // Extended method — not on base VardStore interface, but available
44
+ // for Next.js users who import from @vard/sdk/next
45
+ async prefetch() {
46
+ if (resolvedValues) return;
47
+ if (!fetchPromise) {
48
+ fetchPromise = fetchValues();
49
+ }
50
+ resolvedValues = await fetchPromise;
51
+ }
52
+ };
53
+ }
54
+ async function prefetchVardValues(adapter) {
55
+ await adapter.prefetch();
56
+ }
57
+ export {
58
+ createVardNextAdapter,
59
+ prefetchVardValues
60
+ };
61
+ //# sourceMappingURL=next.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/next.ts"],"sourcesContent":["/**\n * @vard/sdk — Next.js adapter\n *\n * This module provides a VardStore implementation that reads variable values\n * from the Vard API at request time (App Router) or build time (static export).\n *\n * Usage in your Next.js site:\n *\n * // lib/vard.ts\n * import { createVardNextAdapter } from \"@vard/sdk/next\"\n * import { createVard } from \"@vard/sdk\"\n *\n * export const vard = createVard({\n * workspaceId: process.env.VARD_WORKSPACE_ID,\n * store: createVardNextAdapter(),\n * })\n *\n * The adapter fetches variable values from the Vard API:\n * GET https://api.vard.app/v1/workspaces/{workspaceId}/variables\n *\n * In local development (no VARD_WORKSPACE_ID set) it silently falls back\n * to default values so your site works without any Vard account.\n */\n\nimport type { VardStore } from \"./types\";\n\nexport interface VardNextAdapterOptions {\n /**\n * Base URL of the Vard API. Defaults to https://api.vard.app\n */\n apiBase?: string;\n\n /**\n * Workspace ID. Falls back to process.env.VARD_WORKSPACE_ID.\n */\n workspaceId?: string;\n\n /**\n * API Key for authentication. Falls back to process.env.VARD_API_KEY.\n */\n apiKey?: string;\n\n /**\n * Next.js fetch cache strategy. Defaults to \"force-cache\" (SSG-friendly).\n * Use \"no-store\" for fully dynamic pages.\n */\n cache?: RequestCache;\n\n /**\n * Next.js ISR revalidation interval in seconds.\n * Only applies when cache is \"force-cache\".\n */\n revalidate?: number;\n}\n\n/**\n * Creates a VardStore that fetches live variable values from the Vard API.\n * Designed for use inside Next.js App Router (server components, server actions).\n *\n * Values are fetched once per request and cached in a simple Map.\n * In local dev with no workspaceId, returns undefined for every key (defaults take over).\n */\nexport function createVardNextAdapter(\n options: VardNextAdapterOptions = {}\n): VardStore {\n const {\n apiBase = \"https://api.vard.app\",\n workspaceId = process.env.VARD_WORKSPACE_ID,\n apiKey = process.env.VARD_API_KEY,\n cache = \"force-cache\",\n revalidate = 60,\n } = options;\n\n // In-memory cache per module instance (one Node.js process = one workspace)\n let resolvedValues: Map<string, unknown> | null = null;\n let fetchPromise: Promise<Map<string, unknown>> | null = null;\n\n async function fetchValues(): Promise<Map<string, unknown>> {\n if (!apiKey && !workspaceId) {\n return new Map();\n }\n\n // New format uses API Key and points to a generic content endpoint\n // Old format uses workspaceId and points to a workspace-specific endpoint\n const url = apiKey \n ? `${apiBase}/api/content/variables`\n : `${apiBase}/v1/workspaces/${workspaceId}/variables`;\n\n try {\n const res = await fetch(url, {\n cache,\n headers: {\n ...(apiKey ? { \"X-Vard-API-Key\": apiKey } : {}),\n },\n // Next.js specific: revalidation hint\n ...(revalidate !== undefined && cache === \"force-cache\"\n ? { next: { revalidate } }\n : {}),\n });\n\n if (!res.ok) {\n console.warn(\n `[vard] Failed to fetch variables: ${res.status}`\n );\n return new Map();\n }\n\n const data = (await res.json()) as { key: string; value: unknown }[];\n return new Map(data.map((v) => [v.key, v.value]));\n } catch (err) {\n console.warn(\"[vard] Error fetching variable values:\", err);\n return new Map();\n }\n }\n\n return {\n get(key: string): unknown {\n // Synchronous path — values must have been pre-fetched.\n // In Next.js App Router, call vard.prefetch() in your layout/page\n // before rendering, or use the async helper below.\n return resolvedValues?.get(key);\n },\n\n // Extended method — not on base VardStore interface, but available\n // for Next.js users who import from @vard/sdk/next\n async prefetch(): Promise<void> {\n if (resolvedValues) return;\n if (!fetchPromise) {\n fetchPromise = fetchValues();\n }\n resolvedValues = await fetchPromise;\n },\n } as VardStore & { prefetch(): Promise<void> };\n}\n\n/**\n * A convenience wrapper that creates a Vard client pre-loaded with live values.\n * Call this once in your Next.js layout before rendering any server component\n * that uses vard variables.\n *\n * @example\n * // app/layout.tsx\n * import { prefetchVardValues } from \"@vard/sdk/next\"\n * import { vard } from \"@/lib/vard\"\n *\n * export default async function RootLayout({ children }) {\n * await prefetchVardValues(vard)\n * return <html>...</html>\n * }\n */\nexport async function prefetchVardValues(\n adapter: { prefetch(): Promise<void> }\n): Promise<void> {\n await adapter.prefetch();\n}\n"],"mappings":";AA8DO,SAAS,sBACd,UAAkC,CAAC,GACxB;AACX,QAAM;AAAA,IACJ,UAAU;AAAA,IACV,cAAc,QAAQ,IAAI;AAAA,IAC1B,SAAS,QAAQ,IAAI;AAAA,IACrB,QAAQ;AAAA,IACR,aAAa;AAAA,EACf,IAAI;AAGJ,MAAI,iBAA8C;AAClD,MAAI,eAAqD;AAEzD,iBAAe,cAA6C;AAC1D,QAAI,CAAC,UAAU,CAAC,aAAa;AAC3B,aAAO,oBAAI,IAAI;AAAA,IACjB;AAIA,UAAM,MAAM,SACR,GAAG,OAAO,2BACV,GAAG,OAAO,kBAAkB,WAAW;AAE3C,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,KAAK;AAAA,QAC3B;AAAA,QACA,SAAS;AAAA,UACP,GAAI,SAAS,EAAE,kBAAkB,OAAO,IAAI,CAAC;AAAA,QAC/C;AAAA;AAAA,QAEA,GAAI,eAAe,UAAa,UAAU,gBACtC,EAAE,MAAM,EAAE,WAAW,EAAE,IACvB,CAAC;AAAA,MACP,CAAC;AAED,UAAI,CAAC,IAAI,IAAI;AACX,gBAAQ;AAAA,UACN,qCAAqC,IAAI,MAAM;AAAA,QACjD;AACA,eAAO,oBAAI,IAAI;AAAA,MACjB;AAEA,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,aAAO,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAAA,IAClD,SAAS,KAAK;AACZ,cAAQ,KAAK,0CAA0C,GAAG;AAC1D,aAAO,oBAAI,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,IAAI,KAAsB;AAIxB,aAAO,gBAAgB,IAAI,GAAG;AAAA,IAChC;AAAA;AAAA;AAAA,IAIA,MAAM,WAA0B;AAC9B,UAAI,eAAgB;AACpB,UAAI,CAAC,cAAc;AACjB,uBAAe,YAAY;AAAA,MAC7B;AACA,uBAAiB,MAAM;AAAA,IACzB;AAAA,EACF;AACF;AAiBA,eAAsB,mBACpB,SACe;AACf,QAAM,QAAQ,SAAS;AACzB;","names":[]}
@@ -0,0 +1,82 @@
1
+ type VardVariableType = "string" | "richtext" | "color" | "image" | "boolean" | "list";
2
+ type VardListItemSchema = Record<string, "string" | "richtext" | "color" | "image" | "boolean">;
3
+ type InferListItem<S extends VardListItemSchema> = {
4
+ [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;
5
+ };
6
+ type VardRole = "owner" | "developer" | "member" | "viewer";
7
+ interface VardVariableDefinition<T = unknown> {
8
+ /** Dot-notation key, e.g. "hero.title" */
9
+ key: string;
10
+ /** Human-readable label shown in the client portal */
11
+ label: string;
12
+ type: VardVariableType;
13
+ /** The default value baked into the codebase */
14
+ defaultValue: T;
15
+ /** Minimum role required to edit this variable. Defaults to "member". */
16
+ editableBy: VardRole;
17
+ /** Optional description shown as a hint in the client portal */
18
+ description?: string;
19
+ /** For list variables — the schema of each item */
20
+ listItemSchema?: VardListItemSchema;
21
+ }
22
+ interface VardStore {
23
+ /** Returns a stored value for the given key, or undefined if not set */
24
+ get(key: string): unknown;
25
+ }
26
+ interface VardOptions {
27
+ /**
28
+ * Workspace ID. Required in production so the SDK can look up values.
29
+ * Read from VARD_WORKSPACE_ID env var if not provided.
30
+ */
31
+ workspaceId?: string;
32
+ /**
33
+ * Provide a custom store implementation. Used internally by the Next.js
34
+ * adapter and for testing. Defaults to a no-op in environments where
35
+ * VARD_WORKSPACE_ID is unset (local dev without Vard).
36
+ */
37
+ store?: VardStore;
38
+ }
39
+ interface VardClient {
40
+ /**
41
+ * A plain string variable. e.g. a hero headline, a CTA label.
42
+ *
43
+ * @param key Dot-notation identifier, unique within the workspace
44
+ * @param fallback Default value when no client value is stored
45
+ * @param options Optional label, description, permission
46
+ */
47
+ string(key: string, fallback: string, options?: VardVariableOptions): string;
48
+ /**
49
+ * A rich text (markdown) variable. Rendered as HTML at build time.
50
+ */
51
+ richtext(key: string, fallback: string, options?: VardVariableOptions): string;
52
+ /**
53
+ * A CSS color string (hex, hsl, rgb).
54
+ */
55
+ color(key: string, fallback: string, options?: VardVariableOptions): string;
56
+ /**
57
+ * A URL pointing to an uploaded asset (image, video).
58
+ */
59
+ image(key: string, fallback: string, options?: VardVariableOptions): string;
60
+ /**
61
+ * A boolean feature flag. e.g. show/hide a section.
62
+ */
63
+ boolean(key: string, fallback: boolean, options?: Omit<VardVariableOptions, "type">): boolean;
64
+ /**
65
+ * An ordered list of typed objects. e.g. team members, testimonials.
66
+ *
67
+ * @param schema Defines the shape of each list item
68
+ */
69
+ list<S extends VardListItemSchema>(key: string, schema: S, fallback: InferListItem<S>[], options?: Omit<VardVariableOptions, "type">): InferListItem<S>[];
70
+ /**
71
+ * Returns all registered variable definitions. Used by the CLI scanner
72
+ * and the build pipeline to sync definitions to the Vard API.
73
+ */
74
+ getDefinitions(): VardVariableDefinition[];
75
+ }
76
+ interface VardVariableOptions {
77
+ label?: string;
78
+ description?: string;
79
+ editableBy?: VardRole;
80
+ }
81
+
82
+ export type { InferListItem as I, VardOptions as V, VardClient as a, VardListItemSchema as b, VardRole as c, VardStore as d, VardVariableDefinition as e, VardVariableOptions as f, VardVariableType as g };
@@ -0,0 +1,82 @@
1
+ type VardVariableType = "string" | "richtext" | "color" | "image" | "boolean" | "list";
2
+ type VardListItemSchema = Record<string, "string" | "richtext" | "color" | "image" | "boolean">;
3
+ type InferListItem<S extends VardListItemSchema> = {
4
+ [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;
5
+ };
6
+ type VardRole = "owner" | "developer" | "member" | "viewer";
7
+ interface VardVariableDefinition<T = unknown> {
8
+ /** Dot-notation key, e.g. "hero.title" */
9
+ key: string;
10
+ /** Human-readable label shown in the client portal */
11
+ label: string;
12
+ type: VardVariableType;
13
+ /** The default value baked into the codebase */
14
+ defaultValue: T;
15
+ /** Minimum role required to edit this variable. Defaults to "member". */
16
+ editableBy: VardRole;
17
+ /** Optional description shown as a hint in the client portal */
18
+ description?: string;
19
+ /** For list variables — the schema of each item */
20
+ listItemSchema?: VardListItemSchema;
21
+ }
22
+ interface VardStore {
23
+ /** Returns a stored value for the given key, or undefined if not set */
24
+ get(key: string): unknown;
25
+ }
26
+ interface VardOptions {
27
+ /**
28
+ * Workspace ID. Required in production so the SDK can look up values.
29
+ * Read from VARD_WORKSPACE_ID env var if not provided.
30
+ */
31
+ workspaceId?: string;
32
+ /**
33
+ * Provide a custom store implementation. Used internally by the Next.js
34
+ * adapter and for testing. Defaults to a no-op in environments where
35
+ * VARD_WORKSPACE_ID is unset (local dev without Vard).
36
+ */
37
+ store?: VardStore;
38
+ }
39
+ interface VardClient {
40
+ /**
41
+ * A plain string variable. e.g. a hero headline, a CTA label.
42
+ *
43
+ * @param key Dot-notation identifier, unique within the workspace
44
+ * @param fallback Default value when no client value is stored
45
+ * @param options Optional label, description, permission
46
+ */
47
+ string(key: string, fallback: string, options?: VardVariableOptions): string;
48
+ /**
49
+ * A rich text (markdown) variable. Rendered as HTML at build time.
50
+ */
51
+ richtext(key: string, fallback: string, options?: VardVariableOptions): string;
52
+ /**
53
+ * A CSS color string (hex, hsl, rgb).
54
+ */
55
+ color(key: string, fallback: string, options?: VardVariableOptions): string;
56
+ /**
57
+ * A URL pointing to an uploaded asset (image, video).
58
+ */
59
+ image(key: string, fallback: string, options?: VardVariableOptions): string;
60
+ /**
61
+ * A boolean feature flag. e.g. show/hide a section.
62
+ */
63
+ boolean(key: string, fallback: boolean, options?: Omit<VardVariableOptions, "type">): boolean;
64
+ /**
65
+ * An ordered list of typed objects. e.g. team members, testimonials.
66
+ *
67
+ * @param schema Defines the shape of each list item
68
+ */
69
+ list<S extends VardListItemSchema>(key: string, schema: S, fallback: InferListItem<S>[], options?: Omit<VardVariableOptions, "type">): InferListItem<S>[];
70
+ /**
71
+ * Returns all registered variable definitions. Used by the CLI scanner
72
+ * and the build pipeline to sync definitions to the Vard API.
73
+ */
74
+ getDefinitions(): VardVariableDefinition[];
75
+ }
76
+ interface VardVariableOptions {
77
+ label?: string;
78
+ description?: string;
79
+ editableBy?: VardRole;
80
+ }
81
+
82
+ export type { InferListItem as I, VardOptions as V, VardClient as a, VardListItemSchema as b, VardRole as c, VardStore as d, VardVariableDefinition as e, VardVariableOptions as f, VardVariableType as g };
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@vard-app/sdk",
3
+ "version": "0.1.0",
4
+ "description": "Vard SDK — annotate variables in your Next.js site for client-editable content",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./next": {
15
+ "types": "./dist/next.d.ts",
16
+ "import": "./dist/next.mjs",
17
+ "require": "./dist/next.js"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "devDependencies": {
24
+ "@types/node": "^20.19.27",
25
+ "tsup": "^8.5.1",
26
+ "typescript": "^5.9.3"
27
+ },
28
+ "peerDependencies": {
29
+ "next": ">=14.0.0",
30
+ "react": ">=18.0.0"
31
+ },
32
+ "peerDependenciesMeta": {
33
+ "next": {
34
+ "optional": true
35
+ },
36
+ "react": {
37
+ "optional": true
38
+ }
39
+ },
40
+ "scripts": {
41
+ "build": "tsup",
42
+ "dev": "tsup --watch",
43
+ "type-check": "tsc --noEmit"
44
+ }
45
+ }