@vexcms/next 0.1.0-alpha.2 → 0.1.0-alpha.21

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.
Files changed (52) hide show
  1. package/README.md +59 -48
  2. package/dist/NextAdminLayout.d.ts +14 -23
  3. package/dist/NextAdminLayout.d.ts.map +1 -1
  4. package/dist/NextAdminLayout.js +3 -20
  5. package/dist/NextAdminLayout.js.map +1 -1
  6. package/dist/NextAdminLayoutClient.d.ts +10 -11
  7. package/dist/NextAdminLayoutClient.d.ts.map +1 -1
  8. package/dist/NextAdminLayoutClient.js +6 -7
  9. package/dist/NextAdminLayoutClient.js.map +1 -1
  10. package/dist/NextAdminPage.d.ts +7 -5
  11. package/dist/NextAdminPage.d.ts.map +1 -1
  12. package/dist/NextAdminPage.js +2 -137
  13. package/dist/NextAdminPage.js.map +1 -1
  14. package/dist/cache/createVexRevalidateRoute.d.ts +88 -0
  15. package/dist/cache/createVexRevalidateRoute.d.ts.map +1 -0
  16. package/dist/cache/createVexServerClient.d.ts +31 -0
  17. package/dist/cache/createVexServerClient.d.ts.map +1 -0
  18. package/dist/cache/index.d.ts +5 -0
  19. package/dist/cache/index.d.ts.map +1 -0
  20. package/dist/cache/index.js +9 -0
  21. package/dist/cache/index.js.map +1 -0
  22. package/dist/cache/types.d.ts +36 -0
  23. package/dist/cache/types.d.ts.map +1 -0
  24. package/dist/chunk-3J7LCKFC.js +129 -0
  25. package/dist/chunk-3J7LCKFC.js.map +1 -0
  26. package/dist/chunk-K4AAS5B5.js +22 -0
  27. package/dist/chunk-K4AAS5B5.js.map +1 -0
  28. package/dist/chunk-KIRSFMPI.js +78 -0
  29. package/dist/chunk-KIRSFMPI.js.map +1 -0
  30. package/dist/chunk-L6N3D6L5.js +155 -0
  31. package/dist/chunk-L6N3D6L5.js.map +1 -0
  32. package/dist/index.d.ts +10 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +48 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/seo/createVexRobots.d.ts +22 -0
  37. package/dist/seo/createVexRobots.d.ts.map +1 -0
  38. package/dist/seo/createVexSitemap.d.ts +41 -0
  39. package/dist/seo/createVexSitemap.d.ts.map +1 -0
  40. package/dist/seo/index.d.ts +5 -0
  41. package/dist/seo/index.d.ts.map +1 -0
  42. package/dist/seo/index.js +13 -0
  43. package/dist/seo/index.js.map +1 -0
  44. package/dist/seo/vexMetadata.d.ts +30 -0
  45. package/dist/seo/vexMetadata.d.ts.map +1 -0
  46. package/dist/seo/vexStaticParams.d.ts +25 -0
  47. package/dist/seo/vexStaticParams.d.ts.map +1 -0
  48. package/dist/testing/index.d.ts +2 -0
  49. package/dist/testing/index.d.ts.map +1 -0
  50. package/dist/testing/index.js +3 -0
  51. package/dist/testing/index.js.map +1 -0
  52. package/package.json +25 -5
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/NextAdminPage.tsx"],"sourcesContent":["import type { CollectionSlug, PaginationResult, VexConfig, VexMediaDocument } from \"@vexcms/core\";\n\nimport {\n livePreviewLayoutCookieName,\n livePreviewPanelCookieName,\n readLivePreviewLayoutCookie,\n readLivePreviewPanelCookie,\n vexConvexApi,\n} from \"@vexcms/core\";\nimport {\n CollectionEditView,\n CollectionListView,\n DashboardView,\n GlobalEditView,\n GlobalsListView,\n MediaCollectionEditView,\n MediaCollectionListView,\n} from \"@vexcms/react\";\nimport { fetchQuery } from \"convex/nextjs\";\nimport { cookies } from \"next/headers\";\n\n/**\n * VexCMS admin page server component for Next.js.\n *\n * An `async` server component that routes by the `[[...slug]]` catch-all\n * params, prefetches Convex data via `fetchQuery`, and renders the correct\n * view component. Does **not** include a layout wrapper — `NextAdminLayout`\n * in `app/admin/layout.tsx` owns the persistent shell.\n *\n * **Route mapping:**\n * | `path` array | View |\n * |---|---|\n * | `[]` or undefined | `DashboardView` |\n * | `[collectionSlug]` | `CollectionListView` with preloaded docs |\n * | `[collectionSlug, \"new\"]` | `CollectionEditView` (empty form) |\n * | `[collectionSlug, documentId]` | `CollectionEditView` with preloaded doc |\n *\n * @param props - Component props\n * @param props.config - The resolved server `VexConfig`, typically the default export of\n * `vex.config.server.ts` — not the client-safe `vex.config.ts`.\n * @param props.params - Next.js 15 async params `{ path?: string[] }`\n * @param props.token - Optional session token forwarded to `fetchQuery` for authenticated reads.\n * @returns The appropriate admin view for the current URL path.\n *\n * @example\n * ```tsx\n * // app/admin/[[...slug]]/page.tsx\n * import { NextAdminPage } from \"@vexcms/next/server\";\n * import config from \"../../../../vex.config.server\";\n *\n * export default function AdminPage({\n * params,\n * }: {\n * params: Promise<{ path?: string[] }>;\n * }) {\n * return <NextAdminPage config={config} params={params} />;\n * }\n * ```\n */\nexport async function NextAdminPage(props: {\n config: VexConfig;\n params: Promise<{ path?: string[] }>;\n token?: string;\n}) {\n const { path = [] } = await props.params;\n const [collectionSlug, documentId] = path;\n const cookieStore = await cookies();\n\n if (!collectionSlug) {\n return <DashboardView />;\n }\n\n if (collectionSlug === \"globals\") {\n if (!documentId) {\n return <GlobalsListView />;\n }\n const globalConfig = props.config.globals.find((g) => g.slug === documentId);\n if (!globalConfig) {\n return (\n <div>\n <p className=\"text-muted-foreground p-6\">Global &quot;{documentId}&quot; not found.</p>\n <p>TODO: add not found view</p>\n </div>\n );\n }\n const global = await fetchQuery(\n vexConvexApi.globals.get,\n { slug: globalConfig.slug },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <GlobalEditView\n global={globalConfig.slug}\n initialData={global}\n initialPreviewPanelOpen={readLivePreviewPanelCookie({\n cookieValue: cookieStore.get(livePreviewPanelCookieName({ slug: globalConfig.slug }))\n ?.value,\n defaultOpen: globalConfig.admin.livePreview?.defaultOpen ?? false,\n })}\n initialPreviewPanelSize={readLivePreviewLayoutCookie({\n cookieValue: cookieStore.get(livePreviewLayoutCookieName({ slug: globalConfig.slug }))\n ?.value,\n })}\n />\n );\n }\n\n const collection = props.config.collections.find((c) => c.slug === collectionSlug);\n const mediaCollection = props.config.mediaCollections.find((mc) => mc.slug === collectionSlug);\n\n if (!collection && !mediaCollection) {\n return (\n <div>\n <p className=\"text-muted-foreground p-6\">\n Collection &quot;{collectionSlug}&quot; not found.\n </p>\n <p>TODO: add not found view</p>\n </div>\n );\n }\n\n if (mediaCollection && documentId) {\n const initialData = await fetchQuery(\n vexConvexApi.get,\n { id: documentId, collection: mediaCollection.slug },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <MediaCollectionEditView\n collection={mediaCollection.slug}\n documentId={documentId}\n initialData={initialData as null | VexMediaDocument}\n />\n );\n }\n\n if (mediaCollection) {\n const numItems = Math.max(\n mediaCollection.admin.table.serverPageSize,\n mediaCollection.admin.table.defaultPageSize,\n );\n const initialData = await fetchQuery(\n vexConvexApi.find,\n {\n collection: collectionSlug as CollectionSlug,\n paginationOpts: { numItems, totalDocs: true, cursor: null },\n },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <MediaCollectionListView\n collection={mediaCollection.slug}\n initialData={initialData as PaginationResult<VexMediaDocument>}\n />\n );\n }\n\n if (collection && documentId) {\n const initialData = await fetchQuery(\n vexConvexApi.get,\n { id: documentId, collection: collection.slug },\n props.token ? { token: props.token } : undefined,\n );\n return (\n <CollectionEditView\n collection={collection.slug}\n documentId={documentId}\n initialData={initialData}\n initialPreviewPanelOpen={readLivePreviewPanelCookie({\n cookieValue: cookieStore.get(livePreviewPanelCookieName({ slug: collection.slug }))\n ?.value,\n defaultOpen: collection.admin.livePreview?.defaultOpen ?? false,\n })}\n initialPreviewPanelSize={readLivePreviewLayoutCookie({\n cookieValue: cookieStore.get(livePreviewLayoutCookieName({ slug: collection.slug }))\n ?.value,\n })}\n />\n );\n }\n\n if (!collection) {\n throw new Error(\"invalid collection slug\");\n }\n\n const numItems = Math.max(\n collection.admin.table.serverPageSize,\n collection.admin.table.defaultPageSize,\n );\n const initialData = await fetchQuery(\n vexConvexApi.findPaginated,\n {\n collection: collectionSlug as CollectionSlug,\n depth: 1,\n paginationOpts: { cursor: null, numItems, totalDocs: true },\n },\n props.token ? { token: props.token } : undefined,\n );\n return <CollectionListView collection={collection.slug} initialData={initialData} />;\n}\n"],"mappings":"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","names":["initialData","numItems"]}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,15 @@ export * from "./NextAdminPage";
2
2
  export * from "./NextAdminLayout";
3
3
  export { relationship, defineCollection } from "@vexcms/react";
4
4
  export { text, number, select, date, url, checkbox, defineConfig, } from "@vexcms/react";
5
- export type { AdminUser, RelationshipFieldInput, RelationshipField, AdminCollectionConfigInput, CollectionConfigInput, CollectionConfig, TextField, NumberField, SelectField, DateField, UrlField, CheckboxField, AdminField, CollectionSlug, VexDocument, VexConfig, VexConfigInput, RelationshipPreviewProps, } from "@vexcms/react";
5
+ export type { AdminUser, RelationshipFieldInput, RelationshipField, AdminCollectionConfigInput, CollectionConfigInput, CollectionConfig, TextField, NumberField, SelectField, DateField, UrlField, CheckboxField, AdminField, CollectionSlug, VexDocument, VexConfig, VexClientConfig, VexClientConfigInput, VexServerConfigInput, RelationshipPreviewProps, } from "@vexcms/react";
6
6
  export type { RelationshipKeysOf, TextKeysOf, SortableKeysOf, RelationshipTargetOf, Populated, PopulateShape, } from "@vexcms/core";
7
+ export { createVexServerClient } from "./cache/createVexServerClient";
8
+ export type { VexServerClientOptions, VexServerClient } from "./cache/types";
9
+ export { createVexRobots } from "./seo/createVexRobots";
10
+ export { createVexSitemap } from "./seo/createVexSitemap";
11
+ export { vexMetadata } from "./seo/vexMetadata";
12
+ export { vexStaticParams } from "./seo/vexStaticParams";
13
+ export { createVexRevalidateRoute } from "./cache/createVexRevalidateRoute";
14
+ export type { CreateVexRevalidateRouteProps } from "./cache/createVexRevalidateRoute";
15
+ export type {} from "./cache/types";
7
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAyBA,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAG/D,OAAO,EACL,IAAI,EACJ,MAAM,EACN,MAAM,EACN,IAAI,EACJ,GAAG,EACH,QAAQ,EACR,YAAY,GACb,MAAM,eAAe,CAAC;AAMvB,YAAY,EACV,SAAS,EAET,sBAAsB,EACtB,iBAAiB,EACjB,0BAA0B,EAC1B,qBAAqB,EACrB,gBAAgB,EAEhB,SAAS,EACT,WAAW,EACX,WAAW,EACX,SAAS,EACT,QAAQ,EACR,aAAa,EAEb,UAAU,EACV,cAAc,EACd,WAAW,EACX,SAAS,EACT,cAAc,EACd,wBAAwB,GACzB,MAAM,eAAe,CAAC;AAYvB,YAAY,EACV,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,oBAAoB,EACpB,SAAS,EACT,aAAa,GACd,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAyBA,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAG/D,OAAO,EACL,IAAI,EACJ,MAAM,EACN,MAAM,EACN,IAAI,EACJ,GAAG,EACH,QAAQ,EACR,YAAY,GACb,MAAM,eAAe,CAAC;AAMvB,YAAY,EACV,SAAS,EAET,sBAAsB,EACtB,iBAAiB,EACjB,0BAA0B,EAC1B,qBAAqB,EACrB,gBAAgB,EAEhB,SAAS,EACT,WAAW,EACX,WAAW,EACX,SAAS,EACT,QAAQ,EACR,aAAa,EAEb,UAAU,EACV,cAAc,EACd,WAAW,EACX,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AAYvB,YAAY,EACV,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,oBAAoB,EACpB,SAAS,EACT,aAAa,GACd,MAAM,cAAc,CAAC;AAKtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,YAAY,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,YAAY,EAAE,6BAA6B,EAAE,MAAM,kCAAkC,CAAC;AACtF,YAAY,EACX,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,48 @@
1
+ import {
2
+ NextAdminPage
3
+ } from "./chunk-L6N3D6L5.js";
4
+ import {
5
+ NextAdminLayout
6
+ } from "./chunk-K4AAS5B5.js";
7
+ import {
8
+ createVexRevalidateRoute,
9
+ createVexServerClient
10
+ } from "./chunk-3J7LCKFC.js";
11
+ import {
12
+ createVexRobots,
13
+ createVexSitemap,
14
+ vexMetadata,
15
+ vexStaticParams
16
+ } from "./chunk-KIRSFMPI.js";
17
+
18
+ // src/index.ts
19
+ import { relationship, defineCollection } from "@vexcms/react";
20
+ import {
21
+ text,
22
+ number,
23
+ select,
24
+ date,
25
+ url,
26
+ checkbox,
27
+ defineConfig
28
+ } from "@vexcms/react";
29
+ export {
30
+ NextAdminLayout,
31
+ NextAdminPage,
32
+ checkbox,
33
+ createVexRevalidateRoute,
34
+ createVexRobots,
35
+ createVexServerClient,
36
+ createVexSitemap,
37
+ date,
38
+ defineCollection,
39
+ defineConfig,
40
+ number,
41
+ relationship,
42
+ select,
43
+ text,
44
+ url,
45
+ vexMetadata,
46
+ vexStaticParams
47
+ };
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// @vexcms/next v0.1.0-alpha.1\n//\n// Two distinct export surfaces:\n//\n// 1. Server / client component entries (sub-path imports — required because\n// \"use client\" can't be mixed with async server components in one bundle):\n// import { NextAdminPage } from \"@vexcms/next/server\" ← async server component\n// import { NextAdminLayout } from \"@vexcms/next/client\" ← \"use client\" component\n//\n// 2. Config / type re-exports (everything below). Re-exports `@vexcms/react`'s\n// HKT-bound config functions and types transitively so Next consumers can\n// import every config function from a single package:\n//\n// import {\n// defineConfig,\n// defineCollection,\n// relationship,\n// text, number, select, date, url, checkbox,\n// } from \"@vexcms/next\";\n//\n// `admin.components.preview` slots remain typed as React `ComponentType<P>`\n// via `ReactHKT` because @vexcms/react bound it before re-exporting. See\n// spec 22 Decision 15 for the architectural rationale.\n\n// Server / client surface\nexport * from \"./NextAdminPage\";\nexport * from \"./NextAdminLayout\";\n\n// Config functions — HKT-bound wrappers from @vexcms/react\nexport { relationship, defineCollection } from \"@vexcms/react\";\n\n// Field config functions without component slots (pure pass-through)\nexport {\n text,\n number,\n select,\n date,\n url,\n checkbox,\n defineConfig,\n} from \"@vexcms/react\";\n\n// Public types — HKT-bound where applicable.\n// `*FieldInput` core config types intentionally not re-exported (they collide\n// with React `*FieldInput` component names; users get them via inference\n// through the config functions).\nexport type {\n AdminUser,\n // HKT-bound (admin.components.preview = React ComponentType)\n RelationshipFieldInput,\n RelationshipField,\n AdminCollectionConfigInput,\n CollectionConfigInput,\n CollectionConfig,\n // Resolved field types\n TextField,\n NumberField,\n SelectField,\n DateField,\n UrlField,\n CheckboxField,\n // Shared types\n AdminField,\n CollectionSlug,\n VexDocument,\n VexConfig,\n VexClientConfig,\n VexClientConfigInput,\n VexServerConfigInput,\n RelationshipPreviewProps,\n} from \"@vexcms/react\";\n\n// API functions are NOT re-exported from this barrel because @vexcms/next's\n// root index.ts is imported by server components (NextAdminPage). Pulling\n// @vexcms/core/client here would transitively import @convex-dev/react-query\n// which uses createContext — crashing RSC.\n//\n// Import directly from the correct environment-specific path instead:\n//\n// import { find, get, search } from \"@vexcms/core/client\"; ← React components\n// import { find, get, search } from \"@vexcms/core/server\"; ← Convex handlers\n\nexport type {\n RelationshipKeysOf,\n TextKeysOf,\n SortableKeysOf,\n RelationshipTargetOf,\n Populated,\n PopulateShape,\n} from \"@vexcms/core\";\n\n// Cache / SEO surface — server-only, no client context, so these are safe in\n// this RSC-imported root barrel. Also reachable via the \"@vexcms/next/cache\"\n// and \"@vexcms/next/seo\" subpaths.\nexport { createVexServerClient } from \"./cache/createVexServerClient\";\nexport type { VexServerClientOptions, VexServerClient } from \"./cache/types\";\nexport { createVexRobots } from \"./seo/createVexRobots\";\nexport { createVexSitemap } from \"./seo/createVexSitemap\";\nexport { vexMetadata } from \"./seo/vexMetadata\";\nexport { vexStaticParams } from \"./seo/vexStaticParams\";\nexport { createVexRevalidateRoute } from \"./cache/createVexRevalidateRoute\";\nexport type { CreateVexRevalidateRouteProps } from \"./cache/createVexRevalidateRoute\";\nexport type {\n} from \"./cache/types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AA6BA,SAAS,cAAc,wBAAwB;AAG/C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
@@ -0,0 +1,22 @@
1
+ import type { MetadataRoute } from "next";
2
+ /**
3
+ * Creates a Next.js `robots.ts` default export that allows crawlers across the
4
+ * site and points them at the generated sitemap.
5
+ *
6
+ * @param props - Robots configuration.
7
+ * @returns A `robots()` function suitable as `app/robots.ts`'s default export.
8
+ */
9
+ export declare function createVexRobots(props: {
10
+ /**
11
+ * Paths to disallow. Every vexcms template passes `["/admin", "/api"]` — the
12
+ * admin panel is authenticated and neither belongs in an index. Omitted
13
+ * entirely when absent or empty, rather than emitted as an empty array.
14
+ */
15
+ disallow?: string[];
16
+ /**
17
+ * The site's absolute origin, no trailing slash (e.g. `https://example.com`).
18
+ * The sitemap URL is derived as `${siteUrl}/sitemap.xml`.
19
+ */
20
+ siteUrl: string;
21
+ }): () => MetadataRoute.Robots;
22
+ //# sourceMappingURL=createVexRobots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createVexRobots.d.ts","sourceRoot":"","sources":["../../src/seo/createVexRobots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,aAAa,CAAC,MAAM,CAY7B"}
@@ -0,0 +1,41 @@
1
+ import type { FunctionReference, FunctionReturnType, OptionalRestArgs } from "convex/server";
2
+ import type { MetadataRoute } from "next";
3
+ import type { VexServerClient } from "../cache/types";
4
+ type ArrayItem<T> = T extends (infer Item)[] ? Item : never;
5
+ /**
6
+ * Creates a Next.js `sitemap.ts` default export from a Convex published-slugs
7
+ * query (`packages/core/src/api/publishedSlugs/server.ts`).
8
+ *
9
+ * Tolerates an unreachable Convex deployment (P-020): a read failure returns
10
+ * `[]` — an empty sitemap — rather than failing the build.
11
+ *
12
+ * @param props - Sitemap configuration.
13
+ * @returns A `sitemap()` function suitable as `app/sitemap.ts`'s default export.
14
+ */
15
+ export declare function createVexSitemap<Query extends FunctionReference<"query">>(props: {
16
+ args?: OptionalRestArgs<Query>[0];
17
+ client: VexServerClient;
18
+ getSlug: (item: ArrayItem<FunctionReturnType<Query>>) => string;
19
+ /**
20
+ * Optional last-modified extractor. Omit it when the collection carries no
21
+ * modification timestamp — Convex's `_creationTime` is set at insert and
22
+ * never moves, so reporting it as `lastModified` would be a lie.
23
+ * `lastModified` is optional in the sitemap protocol; an absent value is
24
+ * correct, a wrong one costs crawl budget.
25
+ *
26
+ * May return `undefined` for an individual item, and that is the common
27
+ * case: `defineCollection` injects `updatedAt` on every content collection,
28
+ * but only a write through `create`/`update` populates it — a seeded or
29
+ * imported row has none. Those entries are emitted with no `lastModified`
30
+ * rather than an `Invalid Date`.
31
+ */
32
+ getUpdatedAt?: (item: ArrayItem<FunctionReturnType<Query>>) => number | undefined;
33
+ /**
34
+ * Maps one item's slug to its absolute public URL — the route mapper, so URL
35
+ * shape (e.g. `/blog/[slug]` vs `/[slug]`) is the caller's choice.
36
+ */
37
+ toUrl: (slug: string) => string;
38
+ query: Query;
39
+ }): () => Promise<MetadataRoute.Sitemap>;
40
+ export {};
41
+ //# sourceMappingURL=createVexSitemap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createVexSitemap.d.ts","sourceRoot":"","sources":["../../src/seo/createVexSitemap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,GAAG,IAAI,GAAG,KAAK,CAAC;AAE5D;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE;IAChF,IAAI,CAAC,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,KAAK,MAAM,CAAC;IAChE;;;;;;;;;;;;OAYG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IAClF;;;OAGG;IACH,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,KAAK,EAAE,KAAK,CAAC;CACd,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CA6BvC"}
@@ -0,0 +1,5 @@
1
+ export { createVexRobots } from "./createVexRobots";
2
+ export { createVexSitemap } from "./createVexSitemap";
3
+ export { vexMetadata } from "./vexMetadata";
4
+ export { vexStaticParams } from "./vexStaticParams";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/seo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import {
2
+ createVexRobots,
3
+ createVexSitemap,
4
+ vexMetadata,
5
+ vexStaticParams
6
+ } from "../chunk-KIRSFMPI.js";
7
+ export {
8
+ createVexRobots,
9
+ createVexSitemap,
10
+ vexMetadata,
11
+ vexStaticParams
12
+ };
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,30 @@
1
+ import type { Metadata } from "next";
2
+ /**
3
+ * Builds a Next.js `Metadata` object with unconditional title/description, a
4
+ * conditional OG image, `metadataBase`, and a canonical link.
5
+ *
6
+ * Generalizes what Step 1 fixed by hand in `apps/www/src/lib/metadata.ts`:
7
+ * title and description are set regardless of whether an OG image resolved —
8
+ * only the `openGraph.images` entry is conditional on `props.imageUrl`. The
9
+ * original gated the whole `openGraph` block on the image, so a page without
10
+ * one published no OG title or description at all.
11
+ *
12
+ * This FORMATS metadata; it does not read Convex. Resolving which title and
13
+ * description win is the caller's job, because only the caller knows the
14
+ * page/site precedence rules.
15
+ *
16
+ * @param props - Metadata inputs.
17
+ * @returns A `Metadata` object for a page's `generateMetadata` or static
18
+ * `metadata` export.
19
+ */
20
+ export declare function vexMetadata(props: {
21
+ description?: string;
22
+ /** Absolute OG image URL. Omit to emit `openGraph` without an image. */
23
+ imageUrl?: string;
24
+ /** The page's path (e.g. `/about`), used for the canonical link. */
25
+ path: string;
26
+ /** The site's absolute origin, used for `metadataBase`. */
27
+ siteUrl: string;
28
+ title: string;
29
+ }): Metadata;
30
+ //# sourceMappingURL=vexMetadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vexMetadata.d.ts","sourceRoot":"","sources":["../../src/seo/vexMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAErC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,QAAQ,CAkBX"}
@@ -0,0 +1,25 @@
1
+ import type { FunctionReference, FunctionReturnType, OptionalRestArgs } from "convex/server";
2
+ import type { VexServerClient } from "../cache/types";
3
+ type ArrayItem<T> = T extends (infer Item)[] ? Item : never;
4
+ /**
5
+ * Builds Next.js `generateStaticParams` output for a slug-driven route from a
6
+ * Convex query.
7
+ *
8
+ * Returns `[]` when the read fails — including an unreachable Convex
9
+ * deployment, which every CI build hits because it supplies placeholder env
10
+ * rather than skipping validation (P-020). A route with no static params still
11
+ * renders correctly on demand; it is simply not prerendered until the next
12
+ * build.
13
+ *
14
+ * @param props - Static params configuration.
15
+ * @returns `{ [paramName]: string }[]`, or `[]` if the read fails.
16
+ */
17
+ export declare function vexStaticParams<Query extends FunctionReference<"query">>(props: {
18
+ args?: OptionalRestArgs<Query>[0];
19
+ client: VexServerClient;
20
+ getSlug: (item: ArrayItem<FunctionReturnType<Query>>) => string;
21
+ paramName: string;
22
+ query: Query;
23
+ }): Promise<Record<string, string>[]>;
24
+ export {};
25
+ //# sourceMappingURL=vexStaticParams.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vexStaticParams.d.ts","sourceRoot":"","sources":["../../src/seo/vexStaticParams.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE7F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,GAAG,IAAI,GAAG,KAAK,CAAC;AAE5D;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE;IACrF,IAAI,CAAC,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,KAAK,MAAM,CAAC;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;CACd,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAiBpC"}
@@ -0,0 +1,2 @@
1
+ export * from "@vexcms/react/testing";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAKA,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,3 @@
1
+ // src/testing/index.ts
2
+ export * from "@vexcms/react/testing";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/testing/index.ts"],"sourcesContent":["// Re-exports the full public surface of `@vexcms/react/testing` so Next.js\n// consumers can import the entire VexCMS test kit from `@vexcms/next`\n// without also depending on `@vexcms/react` directly. A wildcard re-export\n// (rather than an enumerated list) keeps this file in sync automatically as\n// `@vexcms/react/testing`'s own surface grows.\nexport * from \"@vexcms/react/testing\";\n"],"mappings":";AAKA,cAAc;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vexcms/next",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.21",
4
4
  "description": "Next.js adapter and admin routes for VexCMS",
5
5
  "keywords": [
6
6
  "cms",
@@ -43,6 +43,21 @@
43
43
  "import": "./dist/NextAdminLayout.js",
44
44
  "types": "./dist/NextAdminLayout.d.ts"
45
45
  },
46
+ "./cache": {
47
+ "source": "./src/cache/index.ts",
48
+ "import": "./dist/cache/index.js",
49
+ "types": "./dist/cache/index.d.ts"
50
+ },
51
+ "./seo": {
52
+ "source": "./src/seo/index.ts",
53
+ "import": "./dist/seo/index.js",
54
+ "types": "./dist/seo/index.d.ts"
55
+ },
56
+ "./testing": {
57
+ "source": "./src/testing/index.ts",
58
+ "import": "./dist/testing/index.js",
59
+ "types": "./dist/testing/index.d.ts"
60
+ },
46
61
  "./styles": "./styles.css"
47
62
  },
48
63
  "publishConfig": {
@@ -51,8 +66,8 @@
51
66
  },
52
67
  "dependencies": {
53
68
  "lucide-react": "0.577.0",
54
- "@vexcms/core": "0.1.0-alpha.2",
55
- "@vexcms/react": "0.1.0-alpha.2"
69
+ "@vexcms/core": "0.1.0-alpha.21",
70
+ "@vexcms/react": "0.1.0-alpha.21"
56
71
  },
57
72
  "devDependencies": {
58
73
  "@convex-dev/react-query": "0.1.0",
@@ -62,6 +77,7 @@
62
77
  "@types/node": "20.19.43",
63
78
  "@types/react": "19.2.17",
64
79
  "@types/react-dom": "19.2.3",
80
+ "@vitest/coverage-v8": "4.1.10",
65
81
  "convex": "1.44.0",
66
82
  "next": "16.3.3",
67
83
  "nuqs": "2.9.0",
@@ -70,6 +86,7 @@
70
86
  "tailwindcss": "4.3.2",
71
87
  "tsup": "8.5.1",
72
88
  "typescript": "6.0.3",
89
+ "vitest": "4.1.10",
73
90
  "zod": "4.4.3",
74
91
  "@vexcms/tsconfig": "0.0.0"
75
92
  },
@@ -87,8 +104,11 @@
87
104
  },
88
105
  "scripts": {
89
106
  "build": "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",
90
- "dev": "tsup --watch --no-clean",
107
+ "dev": "tsup --watch src --no-clean",
91
108
  "clean": "rm -rf dist",
92
- "typecheck": "tsc --noEmit -p tsconfig.check.json"
109
+ "typecheck": "tsc --noEmit -p tsconfig.check.json",
110
+ "test": "vitest run",
111
+ "coverage": "vitest run --coverage",
112
+ "test:watch": "vitest"
93
113
  }
94
114
  }