convex-cms 0.0.2 → 0.0.3
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/admin-dist/nitro.json +15 -0
- package/admin-dist/public/assets/CmsEmptyState-CRswfTzk.js +5 -0
- package/admin-dist/public/assets/CmsPageHeader-CirpXndm.js +1 -0
- package/admin-dist/public/assets/CmsStatusBadge-CbEUpQu-.js +1 -0
- package/admin-dist/public/assets/CmsToolbar-BI2nZOXp.js +1 -0
- package/admin-dist/public/assets/ContentEntryEditor-CBeCyK_m.js +4 -0
- package/admin-dist/public/assets/ErrorState-BIVaWmom.js +1 -0
- package/admin-dist/public/assets/TaxonomyFilter-ChaY6Y_x.js +1 -0
- package/admin-dist/public/assets/_contentTypeId-DQ8k_Rvw.js +1 -0
- package/admin-dist/public/assets/_entryId-CKU_glsK.js +1 -0
- package/admin-dist/public/assets/alert-BXjTqrwQ.js +1 -0
- package/admin-dist/public/assets/badge-hvUOzpVZ.js +1 -0
- package/admin-dist/public/assets/circle-check-big-CF_pR17r.js +1 -0
- package/admin-dist/public/assets/command-DU82cJlt.js +1 -0
- package/admin-dist/public/assets/content-_LXl3pp7.js +1 -0
- package/admin-dist/public/assets/content-types-KjxaXGxY.js +2 -0
- package/admin-dist/public/assets/globals-CS6BZ0zp.css +1 -0
- package/admin-dist/public/assets/index-DNGIZHL-.js +1 -0
- package/admin-dist/public/assets/label-KNtpL71g.js +1 -0
- package/admin-dist/public/assets/link-2-Bw2aI4V4.js +1 -0
- package/admin-dist/public/assets/list-sYepHjt_.js +1 -0
- package/admin-dist/public/assets/main-CKj5yfEi.js +97 -0
- package/admin-dist/public/assets/media-Bkrkffm7.js +1 -0
- package/admin-dist/public/assets/new._contentTypeId-C3LstjNs.js +1 -0
- package/admin-dist/public/assets/plus-DUn8v_Xf.js +1 -0
- package/admin-dist/public/assets/rotate-ccw-DJEoHcRI.js +1 -0
- package/admin-dist/public/assets/scroll-area-DfIlT0in.js +1 -0
- package/admin-dist/public/assets/search-MuAUDJKR.js +1 -0
- package/admin-dist/public/assets/select-BD29IXCI.js +1 -0
- package/admin-dist/public/assets/settings-DmMyn_6A.js +1 -0
- package/admin-dist/public/assets/switch-h3Rrnl5i.js +1 -0
- package/admin-dist/public/assets/tabs-imc8h-Dp.js +1 -0
- package/admin-dist/public/assets/taxonomies-dAsrT65H.js +1 -0
- package/admin-dist/public/assets/textarea-BTy7nwzR.js +1 -0
- package/admin-dist/public/assets/trash-SAWKZZHv.js +1 -0
- package/admin-dist/public/assets/triangle-alert-E52Vfeuh.js +1 -0
- package/admin-dist/public/assets/useBreadcrumbLabel-BECBMCzM.js +1 -0
- package/admin-dist/public/assets/usePermissions-Basjs9BT.js +1 -0
- package/admin-dist/public/favicon.ico +0 -0
- package/admin-dist/server/_chunks/_libs/@date-fns/tz.mjs +217 -0
- package/admin-dist/server/_chunks/_libs/@floating-ui/core.mjs +719 -0
- package/admin-dist/server/_chunks/_libs/@floating-ui/dom.mjs +622 -0
- package/admin-dist/server/_chunks/_libs/@floating-ui/react-dom.mjs +292 -0
- package/admin-dist/server/_chunks/_libs/@floating-ui/utils.mjs +320 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/number.mjs +6 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/primitive.mjs +11 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-arrow.mjs +23 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-avatar.mjs +119 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-checkbox.mjs +270 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-collection.mjs +69 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-compose-refs.mjs +39 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-context.mjs +137 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-dialog.mjs +325 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-direction.mjs +9 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-dismissable-layer.mjs +210 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-dropdown-menu.mjs +253 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-focus-guards.mjs +29 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-focus-scope.mjs +206 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-id.mjs +14 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-label.mjs +23 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-menu.mjs +812 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-popover.mjs +300 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-popper.mjs +286 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-portal.mjs +16 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-presence.mjs +128 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-primitive.mjs +141 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-roving-focus.mjs +224 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-scroll-area.mjs +721 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-select.mjs +1163 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-separator.mjs +28 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-slot.mjs +601 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-switch.mjs +152 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-tabs.mjs +189 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-callback-ref.mjs +11 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-controllable-state.mjs +69 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-effect-event.mjs +1 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-escape-keydown.mjs +17 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-is-hydrated.mjs +15 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-layout-effect.mjs +6 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-previous.mjs +14 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-use-size.mjs +39 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-visually-hidden.mjs +33 -0
- package/admin-dist/server/_chunks/_libs/@tanstack/history.mjs +409 -0
- package/admin-dist/server/_chunks/_libs/@tanstack/react-router.mjs +1711 -0
- package/admin-dist/server/_chunks/_libs/@tanstack/react-store.mjs +56 -0
- package/admin-dist/server/_chunks/_libs/@tanstack/router-core.mjs +4829 -0
- package/admin-dist/server/_chunks/_libs/@tanstack/store.mjs +134 -0
- package/admin-dist/server/_chunks/_libs/react-dom.mjs +10781 -0
- package/admin-dist/server/_chunks/_libs/react.mjs +513 -0
- package/admin-dist/server/_libs/aria-hidden.mjs +122 -0
- package/admin-dist/server/_libs/class-variance-authority.mjs +44 -0
- package/admin-dist/server/_libs/clsx.mjs +16 -0
- package/admin-dist/server/_libs/cmdk.mjs +315 -0
- package/admin-dist/server/_libs/convex.mjs +4841 -0
- package/admin-dist/server/_libs/cookie-es.mjs +58 -0
- package/admin-dist/server/_libs/croner.mjs +1 -0
- package/admin-dist/server/_libs/crossws.mjs +1 -0
- package/admin-dist/server/_libs/date-fns.mjs +1716 -0
- package/admin-dist/server/_libs/detect-node-es.mjs +1 -0
- package/admin-dist/server/_libs/get-nonce.mjs +9 -0
- package/admin-dist/server/_libs/h3-v2.mjs +277 -0
- package/admin-dist/server/_libs/h3.mjs +401 -0
- package/admin-dist/server/_libs/hookable.mjs +1 -0
- package/admin-dist/server/_libs/isbot.mjs +20 -0
- package/admin-dist/server/_libs/lucide-react.mjs +850 -0
- package/admin-dist/server/_libs/ohash.mjs +1 -0
- package/admin-dist/server/_libs/react-day-picker.mjs +2201 -0
- package/admin-dist/server/_libs/react-remove-scroll-bar.mjs +82 -0
- package/admin-dist/server/_libs/react-remove-scroll.mjs +328 -0
- package/admin-dist/server/_libs/react-style-singleton.mjs +69 -0
- package/admin-dist/server/_libs/rou3.mjs +8 -0
- package/admin-dist/server/_libs/seroval-plugins.mjs +58 -0
- package/admin-dist/server/_libs/seroval.mjs +1765 -0
- package/admin-dist/server/_libs/srvx.mjs +719 -0
- package/admin-dist/server/_libs/tailwind-merge.mjs +3010 -0
- package/admin-dist/server/_libs/tiny-invariant.mjs +12 -0
- package/admin-dist/server/_libs/tiny-warning.mjs +5 -0
- package/admin-dist/server/_libs/tslib.mjs +39 -0
- package/admin-dist/server/_libs/ufo.mjs +54 -0
- package/admin-dist/server/_libs/unctx.mjs +1 -0
- package/admin-dist/server/_libs/unstorage.mjs +1 -0
- package/admin-dist/server/_libs/use-callback-ref.mjs +66 -0
- package/admin-dist/server/_libs/use-sidecar.mjs +106 -0
- package/admin-dist/server/_libs/use-sync-external-store.mjs +139 -0
- package/admin-dist/server/_libs/zod.mjs +4223 -0
- package/admin-dist/server/_ssr/CmsEmptyState-DU7-7-mV.mjs +290 -0
- package/admin-dist/server/_ssr/CmsPageHeader-CseW0AHm.mjs +24 -0
- package/admin-dist/server/_ssr/CmsStatusBadge-B_pi4KCp.mjs +127 -0
- package/admin-dist/server/_ssr/CmsToolbar-X75ex6ek.mjs +49 -0
- package/admin-dist/server/_ssr/ContentEntryEditor-CepusRsA.mjs +3720 -0
- package/admin-dist/server/_ssr/ErrorState-cI-bKLez.mjs +89 -0
- package/admin-dist/server/_ssr/TaxonomyFilter-Bwrq0-cz.mjs +188 -0
- package/admin-dist/server/_ssr/_contentTypeId-BqYKEcLr.mjs +379 -0
- package/admin-dist/server/_ssr/_entryId-CRfnqeDf.mjs +161 -0
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BwDlABVk.mjs +4 -0
- package/admin-dist/server/_ssr/alert-CVt45UUP.mjs +92 -0
- package/admin-dist/server/_ssr/badge-6BsP37vG.mjs +125 -0
- package/admin-dist/server/_ssr/command-fy8epIKf.mjs +128 -0
- package/admin-dist/server/_ssr/config.server-D7JHDcDv.mjs +117 -0
- package/admin-dist/server/_ssr/content-B5RhL7uW.mjs +532 -0
- package/admin-dist/server/_ssr/content-types-BIOqCQYN.mjs +1166 -0
- package/admin-dist/server/_ssr/index-DHSHDPt1.mjs +193 -0
- package/admin-dist/server/_ssr/index.mjs +1275 -0
- package/admin-dist/server/_ssr/label-C8Dko1j7.mjs +22 -0
- package/admin-dist/server/_ssr/media-CSx3XttC.mjs +1832 -0
- package/admin-dist/server/_ssr/new._contentTypeId-DzanEZQM.mjs +144 -0
- package/admin-dist/server/_ssr/router-DDWcF-kt.mjs +1556 -0
- package/admin-dist/server/_ssr/scroll-area-bjPYwhXN.mjs +59 -0
- package/admin-dist/server/_ssr/select-BUhDDf4T.mjs +142 -0
- package/admin-dist/server/_ssr/settings-DAsxnw2q.mjs +348 -0
- package/admin-dist/server/_ssr/start-HYkvq4Ni.mjs +4 -0
- package/admin-dist/server/_ssr/switch-BgyRtQ1Z.mjs +31 -0
- package/admin-dist/server/_ssr/tabs-DzMdRB1A.mjs +628 -0
- package/admin-dist/server/_ssr/taxonomies-C8j8g5Q5.mjs +915 -0
- package/admin-dist/server/_ssr/textarea-9jNeYJSc.mjs +18 -0
- package/admin-dist/server/_ssr/trash-DYMxwhZB.mjs +291 -0
- package/admin-dist/server/_ssr/useBreadcrumbLabel-FNSAr2Ha.mjs +16 -0
- package/admin-dist/server/_ssr/usePermissions-BJGGahrJ.mjs +68 -0
- package/admin-dist/server/favicon.ico +0 -0
- package/admin-dist/server/index.mjs +627 -0
- package/dist/cli/index.js +0 -0
- package/dist/client/admin-config.d.ts +0 -1
- package/dist/client/admin-config.d.ts.map +1 -1
- package/dist/client/admin-config.js +0 -1
- package/dist/client/admin-config.js.map +1 -1
- package/dist/client/adminApi.d.ts.map +1 -1
- package/dist/client/agentTools.d.ts +1237 -135
- package/dist/client/agentTools.d.ts.map +1 -1
- package/dist/client/agentTools.js +33 -9
- package/dist/client/agentTools.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/component.d.ts +9 -0
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/mediaAssets.d.ts +35 -0
- package/dist/component/mediaAssets.d.ts.map +1 -1
- package/dist/component/mediaAssets.js +81 -0
- package/dist/component/mediaAssets.js.map +1 -1
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +2 -1
- package/dist/test.js.map +1 -1
- package/package.json +9 -5
- package/dist/component/auditLog.d.ts +0 -410
- package/dist/component/auditLog.d.ts.map +0 -1
- package/dist/component/auditLog.js +0 -607
- package/dist/component/auditLog.js.map +0 -1
- package/dist/component/types.d.ts +0 -4
- package/dist/component/types.d.ts.map +0 -1
- package/dist/component/types.js +0 -2
- package/dist/component/types.js.map +0 -1
- package/src/cli/commands/admin.ts +0 -104
- package/src/cli/index.ts +0 -21
- package/src/cli/utils/detectConvexUrl.ts +0 -54
- package/src/cli/utils/openBrowser.ts +0 -16
- package/src/client/admin-config.ts +0 -138
- package/src/client/adminApi.ts +0 -942
- package/src/client/agentTools.ts +0 -1311
- package/src/client/argTypes.ts +0 -316
- package/src/client/field-types.ts +0 -187
- package/src/client/index.ts +0 -1301
- package/src/client/queryBuilder.ts +0 -1100
- package/src/client/schema/codegen.ts +0 -500
- package/src/client/schema/defineContentType.ts +0 -501
- package/src/client/schema/index.ts +0 -169
- package/src/client/schema/schemaDrift.ts +0 -574
- package/src/client/schema/typedClient.ts +0 -688
- package/src/client/schema/types.ts +0 -666
- package/src/client/types.ts +0 -723
- package/src/client/workflows.ts +0 -141
- package/src/client/wrapper.ts +0 -4304
- package/src/component/_generated/api.ts +0 -140
- package/src/component/_generated/component.ts +0 -5029
- package/src/component/_generated/dataModel.ts +0 -60
- package/src/component/_generated/server.ts +0 -156
- package/src/component/authorization.ts +0 -647
- package/src/component/authorizationHooks.ts +0 -668
- package/src/component/bulkOperations.ts +0 -687
- package/src/component/contentEntries.ts +0 -1976
- package/src/component/contentEntryMutations.ts +0 -1223
- package/src/component/contentEntryValidation.ts +0 -707
- package/src/component/contentLock.ts +0 -550
- package/src/component/contentTypeMigration.ts +0 -1064
- package/src/component/contentTypeMutations.ts +0 -969
- package/src/component/contentTypes.ts +0 -346
- package/src/component/convex.config.ts +0 -44
- package/src/component/documentTypes.ts +0 -240
- package/src/component/eventEmitter.ts +0 -485
- package/src/component/exportImport.ts +0 -1169
- package/src/component/index.ts +0 -491
- package/src/component/lib/deepReferenceResolver.ts +0 -999
- package/src/component/lib/errors.ts +0 -816
- package/src/component/lib/index.ts +0 -145
- package/src/component/lib/mediaReferenceResolver.ts +0 -495
- package/src/component/lib/metadataExtractor.ts +0 -792
- package/src/component/lib/mutationAuth.ts +0 -199
- package/src/component/lib/queries.ts +0 -79
- package/src/component/lib/ragContentChunker.ts +0 -1371
- package/src/component/lib/referenceResolver.ts +0 -430
- package/src/component/lib/slugGenerator.ts +0 -262
- package/src/component/lib/slugUniqueness.ts +0 -333
- package/src/component/lib/softDelete.ts +0 -44
- package/src/component/localeFallbackChain.ts +0 -673
- package/src/component/localeFields.ts +0 -896
- package/src/component/mediaAssetMutations.ts +0 -725
- package/src/component/mediaAssets.ts +0 -932
- package/src/component/mediaFolderMutations.ts +0 -1046
- package/src/component/mediaUploadMutations.ts +0 -224
- package/src/component/mediaVariantMutations.ts +0 -900
- package/src/component/mediaVariants.ts +0 -793
- package/src/component/ragContentIndexer.ts +0 -1067
- package/src/component/rateLimitHooks.ts +0 -572
- package/src/component/roles.ts +0 -1360
- package/src/component/scheduledPublish.ts +0 -358
- package/src/component/schema.ts +0 -617
- package/src/component/taxonomies.ts +0 -949
- package/src/component/taxonomyMutations.ts +0 -1210
- package/src/component/trash.ts +0 -724
- package/src/component/userContext.ts +0 -898
- package/src/component/validation.ts +0 -1388
- package/src/component/validators.ts +0 -949
- package/src/component/versionMutations.ts +0 -392
- package/src/component/webhookTrigger.ts +0 -1922
- package/src/react/index.ts +0 -898
- package/src/test.ts +0 -1580
|
@@ -1,666 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type-Safe Schema Definition Types
|
|
3
|
-
*
|
|
4
|
-
* These types enable full TypeScript inference for content type schemas
|
|
5
|
-
* using Convex's native `Infer<typeof validator>` pattern.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* import { v, Infer } from "convex/values";
|
|
10
|
-
* import { defineContentType, InferContentType } from "@convex-cms/core";
|
|
11
|
-
*
|
|
12
|
-
* export const blogPost = defineContentType({
|
|
13
|
-
* name: "blog_post",
|
|
14
|
-
* validator: v.object({
|
|
15
|
-
* title: v.string(),
|
|
16
|
-
* content: v.string(),
|
|
17
|
-
* publishedAt: v.optional(v.number()),
|
|
18
|
-
* }),
|
|
19
|
-
* meta: {
|
|
20
|
-
* displayName: "Blog Post",
|
|
21
|
-
* titleField: "title",
|
|
22
|
-
* },
|
|
23
|
-
* });
|
|
24
|
-
*
|
|
25
|
-
* // Type is inferred automatically
|
|
26
|
-
* type BlogPostData = InferContentType<typeof blogPost>;
|
|
27
|
-
* // { title: string; content: string; publishedAt?: number }
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
import type { Validator } from "convex/values";
|
|
32
|
-
|
|
33
|
-
// =============================================================================
|
|
34
|
-
// Field Metadata Types
|
|
35
|
-
// =============================================================================
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* UI rendering hints for fields in the admin interface.
|
|
39
|
-
* These help the admin UI understand how to render each field type.
|
|
40
|
-
*/
|
|
41
|
-
export type FieldRenderAs =
|
|
42
|
-
| "text"
|
|
43
|
-
| "textarea"
|
|
44
|
-
| "richText"
|
|
45
|
-
| "number"
|
|
46
|
-
| "boolean"
|
|
47
|
-
| "date"
|
|
48
|
-
| "datetime"
|
|
49
|
-
| "reference"
|
|
50
|
-
| "media"
|
|
51
|
-
| "json"
|
|
52
|
-
| "select"
|
|
53
|
-
| "multiSelect"
|
|
54
|
-
| "slug"
|
|
55
|
-
| "code"
|
|
56
|
-
| "color"
|
|
57
|
-
| "url"
|
|
58
|
-
| "email";
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Metadata for a single field within a content type.
|
|
62
|
-
* This provides UI hints, validation configuration, and searchability.
|
|
63
|
-
*
|
|
64
|
-
* All options here correspond to the `options` field in the database
|
|
65
|
-
* field definition format and are passed through to the CMS component.
|
|
66
|
-
*/
|
|
67
|
-
export interface FieldMeta {
|
|
68
|
-
// ==========================================================================
|
|
69
|
-
// General Field Options
|
|
70
|
-
// ==========================================================================
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Human-readable label for the field in the admin UI.
|
|
74
|
-
* If not provided, the field name will be used.
|
|
75
|
-
*/
|
|
76
|
-
label?: string;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Hint for how the admin UI should render this field.
|
|
80
|
-
* Use this to distinguish between field types that share the same
|
|
81
|
-
* validator type (e.g., `richText` vs `text` both use `v.string()`).
|
|
82
|
-
* @default Inferred from validator type
|
|
83
|
-
*/
|
|
84
|
-
renderAs?: FieldRenderAs;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Description/help text shown in the admin UI.
|
|
88
|
-
*/
|
|
89
|
-
description?: string;
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Whether this field should be indexed for search.
|
|
93
|
-
* Only applicable for text-like fields.
|
|
94
|
-
* @default false
|
|
95
|
-
*/
|
|
96
|
-
searchable?: boolean;
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Whether this field supports per-locale values.
|
|
100
|
-
* When true, the field can have different values for each locale.
|
|
101
|
-
* @default false
|
|
102
|
-
*/
|
|
103
|
-
localized?: boolean;
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Placeholder text for input fields.
|
|
107
|
-
*/
|
|
108
|
-
placeholder?: string;
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Display order in the admin UI (lower = earlier).
|
|
112
|
-
*/
|
|
113
|
-
sortOrder?: number;
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* If true, this field is hidden in the admin UI.
|
|
117
|
-
*/
|
|
118
|
-
hidden?: boolean;
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* If true, this field is read-only in the admin UI.
|
|
122
|
-
*/
|
|
123
|
-
readOnly?: boolean;
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Default value for the field.
|
|
127
|
-
* Type depends on the field type.
|
|
128
|
-
*/
|
|
129
|
-
defaultValue?: unknown;
|
|
130
|
-
|
|
131
|
-
// ==========================================================================
|
|
132
|
-
// Text Field Options
|
|
133
|
-
// ==========================================================================
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Minimum length for text fields.
|
|
137
|
-
* Enforced during validation.
|
|
138
|
-
*/
|
|
139
|
-
minLength?: number;
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Maximum length for text fields.
|
|
143
|
-
* Enforced during validation.
|
|
144
|
-
*/
|
|
145
|
-
maxLength?: number;
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Regex pattern for text validation.
|
|
149
|
-
* The content must match this pattern to be valid.
|
|
150
|
-
* @example "^[a-z0-9-]+$" for slug validation
|
|
151
|
-
*/
|
|
152
|
-
pattern?: string;
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Error message to display when pattern validation fails.
|
|
156
|
-
* If not provided, a generic message is shown.
|
|
157
|
-
*/
|
|
158
|
-
patternMessage?: string;
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Whether the text field should render as a multiline textarea.
|
|
162
|
-
* Only applicable when renderAs is "text" or "textarea".
|
|
163
|
-
* @default false
|
|
164
|
-
*/
|
|
165
|
-
multiline?: boolean;
|
|
166
|
-
|
|
167
|
-
// ==========================================================================
|
|
168
|
-
// Number Field Options
|
|
169
|
-
// ==========================================================================
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Minimum value for number fields.
|
|
173
|
-
* Enforced during validation.
|
|
174
|
-
*/
|
|
175
|
-
min?: number;
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Maximum value for number fields.
|
|
179
|
-
* Enforced during validation.
|
|
180
|
-
*/
|
|
181
|
-
max?: number;
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Step increment for number inputs.
|
|
185
|
-
* Used for UI number spinners.
|
|
186
|
-
* @example 0.01 for currency values
|
|
187
|
-
*/
|
|
188
|
-
step?: number;
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Decimal precision for number fields.
|
|
192
|
-
* Numbers will be rounded to this many decimal places.
|
|
193
|
-
* @example 2 for currency (e.g., 19.99)
|
|
194
|
-
*/
|
|
195
|
-
precision?: number;
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Prefix to display before the number input.
|
|
199
|
-
* @example "$" for currency
|
|
200
|
-
*/
|
|
201
|
-
prefix?: string;
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Suffix to display after the number input.
|
|
205
|
-
* @example "%" for percentages
|
|
206
|
-
*/
|
|
207
|
-
suffix?: string;
|
|
208
|
-
|
|
209
|
-
// ==========================================================================
|
|
210
|
-
// Boolean Field Options
|
|
211
|
-
// ==========================================================================
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Label to display when the boolean is true.
|
|
215
|
-
* @example "Yes", "Enabled", "Active"
|
|
216
|
-
*/
|
|
217
|
-
trueLabel?: string;
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Label to display when the boolean is false.
|
|
221
|
-
* @example "No", "Disabled", "Inactive"
|
|
222
|
-
*/
|
|
223
|
-
falseLabel?: string;
|
|
224
|
-
|
|
225
|
-
// ==========================================================================
|
|
226
|
-
// Date/Datetime Field Options
|
|
227
|
-
// ==========================================================================
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Minimum allowed date (ISO 8601 format).
|
|
231
|
-
* @example "2026-01-01"
|
|
232
|
-
*/
|
|
233
|
-
minDate?: string;
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Maximum allowed date (ISO 8601 format).
|
|
237
|
-
* @example "2025-12-31"
|
|
238
|
-
*/
|
|
239
|
-
maxDate?: string;
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* IANA timezone for datetime fields.
|
|
243
|
-
* Used for display and input conversion.
|
|
244
|
-
* @example "America/New_York"
|
|
245
|
-
*/
|
|
246
|
-
timezone?: string;
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Display format for date/datetime fields.
|
|
250
|
-
* Uses date-fns format strings.
|
|
251
|
-
* @example "yyyy-MM-dd" or "PPP" (localized)
|
|
252
|
-
*/
|
|
253
|
-
format?: string;
|
|
254
|
-
|
|
255
|
-
// ==========================================================================
|
|
256
|
-
// Reference Field Options
|
|
257
|
-
// ==========================================================================
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* For reference fields: allowed content type names.
|
|
261
|
-
* If not specified, references to any content type are allowed.
|
|
262
|
-
*/
|
|
263
|
-
allowedContentTypes?: string[];
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Whether multiple references can be selected.
|
|
267
|
-
* When true, the field stores an array of IDs.
|
|
268
|
-
* @default false
|
|
269
|
-
*/
|
|
270
|
-
multiple?: boolean;
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Minimum number of items required (for array fields).
|
|
274
|
-
* Only applies when `multiple` is true.
|
|
275
|
-
*/
|
|
276
|
-
minItems?: number;
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Maximum number of items allowed (for array fields).
|
|
280
|
-
* Only applies when `multiple` is true.
|
|
281
|
-
*/
|
|
282
|
-
maxItems?: number;
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Whether to allow creating new referenced entries inline.
|
|
286
|
-
* @default false
|
|
287
|
-
*/
|
|
288
|
-
allowInlineCreation?: boolean;
|
|
289
|
-
|
|
290
|
-
// ==========================================================================
|
|
291
|
-
// Media Field Options
|
|
292
|
-
// ==========================================================================
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* For media fields: allowed MIME types.
|
|
296
|
-
* @example ["image/jpeg", "image/png", "image/webp"]
|
|
297
|
-
*/
|
|
298
|
-
allowedMimeTypes?: string[];
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Maximum file size in bytes.
|
|
302
|
-
* @example 5 * 1024 * 1024 for 5MB
|
|
303
|
-
*/
|
|
304
|
-
maxFileSize?: number;
|
|
305
|
-
|
|
306
|
-
// ==========================================================================
|
|
307
|
-
// Select/MultiSelect Field Options
|
|
308
|
-
// ==========================================================================
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* For select/multiSelect fields: available options.
|
|
312
|
-
*/
|
|
313
|
-
options?: Array<{ value: string; label: string }>;
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Minimum number of selections required (for multiSelect).
|
|
317
|
-
*/
|
|
318
|
-
minSelections?: number;
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Maximum number of selections allowed (for multiSelect).
|
|
322
|
-
*/
|
|
323
|
-
maxSelections?: number;
|
|
324
|
-
|
|
325
|
-
// ==========================================================================
|
|
326
|
-
// Rich Text Field Options
|
|
327
|
-
// ==========================================================================
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* Allowed block types for rich text fields.
|
|
331
|
-
* @example ["paragraph", "heading", "list", "blockquote"]
|
|
332
|
-
*/
|
|
333
|
-
allowedBlocks?: string[];
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Allowed inline marks/formatting for rich text fields.
|
|
337
|
-
* @example ["bold", "italic", "link", "code"]
|
|
338
|
-
*/
|
|
339
|
-
allowedMarks?: string[];
|
|
340
|
-
|
|
341
|
-
// ==========================================================================
|
|
342
|
-
// JSON Field Options
|
|
343
|
-
// ==========================================================================
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* JSON Schema for validating the JSON field content.
|
|
347
|
-
* Should be a valid JSON Schema object.
|
|
348
|
-
*/
|
|
349
|
-
schema?: object;
|
|
350
|
-
|
|
351
|
-
// ==========================================================================
|
|
352
|
-
// Taxonomy Field Options (tags/category)
|
|
353
|
-
// ==========================================================================
|
|
354
|
-
|
|
355
|
-
/**
|
|
356
|
-
* The taxonomy ID to use for this tag/category field.
|
|
357
|
-
* Either taxonomyId or taxonomyName must be provided for taxonomy fields.
|
|
358
|
-
*/
|
|
359
|
-
taxonomyId?: string;
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* The taxonomy name to use for this tag/category field.
|
|
363
|
-
* Alternative to taxonomyId - will look up the taxonomy by name.
|
|
364
|
-
*/
|
|
365
|
-
taxonomyName?: string;
|
|
366
|
-
|
|
367
|
-
/**
|
|
368
|
-
* Whether to allow creating new taxonomy terms inline.
|
|
369
|
-
* @default false
|
|
370
|
-
*/
|
|
371
|
-
allowCreate?: boolean;
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* Maximum number of tags that can be selected.
|
|
375
|
-
*/
|
|
376
|
-
maxTags?: number;
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Minimum number of tags required.
|
|
380
|
-
*/
|
|
381
|
-
minTags?: number;
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* For hierarchical taxonomies: maximum depth level to show.
|
|
385
|
-
* 0 = root only, 1 = root and children, etc.
|
|
386
|
-
*/
|
|
387
|
-
depth?: number;
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* Whether to allow selecting multiple categories (for category fields).
|
|
391
|
-
* @default false
|
|
392
|
-
*/
|
|
393
|
-
allowMultiple?: boolean;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Content type metadata configuration.
|
|
398
|
-
* Provides display information and field-level metadata.
|
|
399
|
-
*/
|
|
400
|
-
export interface ContentTypeMeta<TFieldNames extends string = string> {
|
|
401
|
-
/**
|
|
402
|
-
* Human-readable display name for the content type.
|
|
403
|
-
* Shown in the admin UI.
|
|
404
|
-
*/
|
|
405
|
-
displayName: string;
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Description of this content type.
|
|
409
|
-
*/
|
|
410
|
-
description?: string;
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Icon identifier for the admin UI (e.g., emoji or icon name).
|
|
414
|
-
*/
|
|
415
|
-
icon?: string;
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* Field to use for the entry's title in listings.
|
|
419
|
-
* Must be a key from the validator's object type.
|
|
420
|
-
*/
|
|
421
|
-
titleField?: TFieldNames;
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* Field to use for generating URL slugs.
|
|
425
|
-
* Must be a key from the validator's object type.
|
|
426
|
-
*/
|
|
427
|
-
slugField?: TFieldNames;
|
|
428
|
-
|
|
429
|
-
/**
|
|
430
|
-
* If true, only one entry of this content type can exist.
|
|
431
|
-
*/
|
|
432
|
-
singleton?: boolean;
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
* Display order in admin UI navigation.
|
|
436
|
-
*/
|
|
437
|
-
sortOrder?: number;
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Field-level metadata keyed by field name.
|
|
441
|
-
* Only fields present in the validator can have metadata.
|
|
442
|
-
*/
|
|
443
|
-
fields?: Partial<Record<TFieldNames, FieldMeta>>;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// =============================================================================
|
|
447
|
-
// Content Type Definition Types
|
|
448
|
-
// =============================================================================
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Input configuration for defineContentType().
|
|
452
|
-
*
|
|
453
|
-
* @typeParam TValidator - The Convex validator for the content data shape
|
|
454
|
-
*/
|
|
455
|
-
export interface ContentTypeConfig<
|
|
456
|
-
TValidator extends Validator<Record<string, unknown>, "required", string>
|
|
457
|
-
> {
|
|
458
|
-
/**
|
|
459
|
-
* Unique machine-readable name for this content type.
|
|
460
|
-
* Used as the identifier in code and URLs.
|
|
461
|
-
*
|
|
462
|
-
* Must be:
|
|
463
|
-
* - Lowercase letters, numbers, and underscores only
|
|
464
|
-
* - Start with a letter
|
|
465
|
-
* - 1-50 characters
|
|
466
|
-
*
|
|
467
|
-
* @example "blog_post", "product", "author"
|
|
468
|
-
*/
|
|
469
|
-
name: string;
|
|
470
|
-
|
|
471
|
-
/**
|
|
472
|
-
* Convex validator defining the content data shape.
|
|
473
|
-
* Types are automatically inferred via `Infer<typeof validator>`.
|
|
474
|
-
*
|
|
475
|
-
* Must be a `v.object()` validator.
|
|
476
|
-
*
|
|
477
|
-
* @example
|
|
478
|
-
* ```typescript
|
|
479
|
-
* validator: v.object({
|
|
480
|
-
* title: v.string(),
|
|
481
|
-
* content: v.string(),
|
|
482
|
-
* author: v.id("contentEntries"),
|
|
483
|
-
* })
|
|
484
|
-
* ```
|
|
485
|
-
*/
|
|
486
|
-
validator: TValidator;
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* CMS-specific metadata for display and configuration.
|
|
490
|
-
*/
|
|
491
|
-
meta: ContentTypeMeta<
|
|
492
|
-
TValidator extends Validator<infer T, "required", string>
|
|
493
|
-
? T extends Record<string, unknown>
|
|
494
|
-
? keyof T & string
|
|
495
|
-
: string
|
|
496
|
-
: string
|
|
497
|
-
>;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
/**
|
|
501
|
-
* A fully defined content type with validator and metadata.
|
|
502
|
-
*
|
|
503
|
-
* @typeParam TName - The literal string type for the content type name
|
|
504
|
-
* @typeParam TValidator - The Convex validator for content data
|
|
505
|
-
*/
|
|
506
|
-
export interface ContentTypeDefinition<
|
|
507
|
-
TName extends string = string,
|
|
508
|
-
TValidator extends Validator<Record<string, unknown>, "required", string> = Validator<
|
|
509
|
-
Record<string, unknown>,
|
|
510
|
-
"required",
|
|
511
|
-
string
|
|
512
|
-
>
|
|
513
|
-
> {
|
|
514
|
-
/**
|
|
515
|
-
* The unique identifier for this content type.
|
|
516
|
-
*/
|
|
517
|
-
readonly name: TName;
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* The Convex validator for content data.
|
|
521
|
-
* Use `Infer<typeof definition.validator>` for the TypeScript type.
|
|
522
|
-
*/
|
|
523
|
-
readonly validator: TValidator;
|
|
524
|
-
|
|
525
|
-
/**
|
|
526
|
-
* CMS metadata for display and configuration.
|
|
527
|
-
*/
|
|
528
|
-
readonly meta: ContentTypeMeta;
|
|
529
|
-
|
|
530
|
-
/**
|
|
531
|
-
* Internal marker to identify content type definitions.
|
|
532
|
-
* @internal
|
|
533
|
-
*/
|
|
534
|
-
readonly _type: "content_type_definition";
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
// =============================================================================
|
|
538
|
-
// Type Inference Utilities
|
|
539
|
-
// =============================================================================
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* Infer the TypeScript type for a content type's data from its definition.
|
|
543
|
-
*
|
|
544
|
-
* This is a thin wrapper around Convex's native `Infer<typeof validator>`.
|
|
545
|
-
*
|
|
546
|
-
* @example
|
|
547
|
-
* ```typescript
|
|
548
|
-
* const blogPost = defineContentType({
|
|
549
|
-
* name: "blog_post",
|
|
550
|
-
* validator: v.object({
|
|
551
|
-
* title: v.string(),
|
|
552
|
-
* content: v.string(),
|
|
553
|
-
* }),
|
|
554
|
-
* meta: { displayName: "Blog Post" },
|
|
555
|
-
* });
|
|
556
|
-
*
|
|
557
|
-
* type BlogPostData = InferContentType<typeof blogPost>;
|
|
558
|
-
* // { title: string; content: string }
|
|
559
|
-
* ```
|
|
560
|
-
*/
|
|
561
|
-
export type InferContentType<T extends ContentTypeDefinition> =
|
|
562
|
-
T extends ContentTypeDefinition<string, infer V>
|
|
563
|
-
? V extends Validator<infer Data, "required", string>
|
|
564
|
-
? Data
|
|
565
|
-
: never
|
|
566
|
-
: never;
|
|
567
|
-
|
|
568
|
-
/**
|
|
569
|
-
* A schema object containing multiple content type definitions.
|
|
570
|
-
*
|
|
571
|
-
* @example
|
|
572
|
-
* ```typescript
|
|
573
|
-
* export const contentSchema = {
|
|
574
|
-
* blogPost,
|
|
575
|
-
* author,
|
|
576
|
-
* product,
|
|
577
|
-
* } satisfies ContentSchema;
|
|
578
|
-
* ```
|
|
579
|
-
*/
|
|
580
|
-
export type ContentSchema = Record<string, ContentTypeDefinition>;
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
* Infer all content data types from a schema object.
|
|
584
|
-
*
|
|
585
|
-
* Returns a mapped type where:
|
|
586
|
-
* - Keys are the content type names (from the `name` property)
|
|
587
|
-
* - Values are the inferred data types
|
|
588
|
-
*
|
|
589
|
-
* @example
|
|
590
|
-
* ```typescript
|
|
591
|
-
* const contentSchema = { blogPost, author, product };
|
|
592
|
-
*
|
|
593
|
-
* type ContentTypes = InferSchema<typeof contentSchema>;
|
|
594
|
-
* // {
|
|
595
|
-
* // blog_post: { title: string; content: string; ... };
|
|
596
|
-
* // author: { name: string; bio?: string; ... };
|
|
597
|
-
* // product: { name: string; price: number; ... };
|
|
598
|
-
* // }
|
|
599
|
-
* ```
|
|
600
|
-
*/
|
|
601
|
-
export type InferSchema<T extends ContentSchema> = {
|
|
602
|
-
[K in keyof T as T[K] extends ContentTypeDefinition<infer Name, Validator<Record<string, unknown>, "required", string>>
|
|
603
|
-
? Name
|
|
604
|
-
: never]: T[K] extends ContentTypeDefinition<string, infer V>
|
|
605
|
-
? V extends Validator<infer Data, "required", string>
|
|
606
|
-
? Data
|
|
607
|
-
: never
|
|
608
|
-
: never;
|
|
609
|
-
};
|
|
610
|
-
|
|
611
|
-
/**
|
|
612
|
-
* Extract all content type names from a schema.
|
|
613
|
-
*
|
|
614
|
-
* @example
|
|
615
|
-
* ```typescript
|
|
616
|
-
* type Names = SchemaContentTypeNames<typeof contentSchema>;
|
|
617
|
-
* // "blog_post" | "author" | "product"
|
|
618
|
-
* ```
|
|
619
|
-
*/
|
|
620
|
-
export type SchemaContentTypeNames<T extends ContentSchema> = {
|
|
621
|
-
[K in keyof T]: T[K] extends ContentTypeDefinition<infer Name, Validator<Record<string, unknown>, "required", string>>
|
|
622
|
-
? Name
|
|
623
|
-
: never;
|
|
624
|
-
}[keyof T];
|
|
625
|
-
|
|
626
|
-
/**
|
|
627
|
-
* Get the data type for a specific content type name from a schema.
|
|
628
|
-
*
|
|
629
|
-
* @example
|
|
630
|
-
* ```typescript
|
|
631
|
-
* type BlogData = SchemaContentType<typeof contentSchema, "blog_post">;
|
|
632
|
-
* // { title: string; content: string; ... }
|
|
633
|
-
* ```
|
|
634
|
-
*/
|
|
635
|
-
export type SchemaContentType<
|
|
636
|
-
T extends ContentSchema,
|
|
637
|
-
Name extends SchemaContentTypeNames<T>
|
|
638
|
-
> = InferSchema<T>[Name];
|
|
639
|
-
|
|
640
|
-
// =============================================================================
|
|
641
|
-
// Runtime Schema Utilities
|
|
642
|
-
// =============================================================================
|
|
643
|
-
|
|
644
|
-
/**
|
|
645
|
-
* Extract field names from a content type definition.
|
|
646
|
-
*/
|
|
647
|
-
export type ContentTypeFieldNames<T extends ContentTypeDefinition> =
|
|
648
|
-
T extends ContentTypeDefinition<string, infer V>
|
|
649
|
-
? V extends Validator<infer Data, "required", string>
|
|
650
|
-
? Data extends Record<string, unknown>
|
|
651
|
-
? keyof Data & string
|
|
652
|
-
: never
|
|
653
|
-
: never
|
|
654
|
-
: never;
|
|
655
|
-
|
|
656
|
-
/**
|
|
657
|
-
* Check if a value is a ContentTypeDefinition.
|
|
658
|
-
*/
|
|
659
|
-
export function isContentTypeDefinition(value: unknown): value is ContentTypeDefinition {
|
|
660
|
-
return (
|
|
661
|
-
typeof value === "object" &&
|
|
662
|
-
value !== null &&
|
|
663
|
-
"_type" in value &&
|
|
664
|
-
(value as ContentTypeDefinition)._type === "content_type_definition"
|
|
665
|
-
);
|
|
666
|
-
}
|