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,224 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Media Upload Mutation Functions
|
|
3
|
-
*
|
|
4
|
-
* Provides mutation functions for generating upload URLs for client-side file uploads.
|
|
5
|
-
* Uses Convex's built-in file storage system which handles the actual file storage.
|
|
6
|
-
*
|
|
7
|
-
* Upload Flow:
|
|
8
|
-
* 1. Client calls generateUploadUrl to get a temporary upload URL
|
|
9
|
-
* 2. Client POSTs the file directly to the upload URL
|
|
10
|
-
* 3. Client receives a storageId from the upload response
|
|
11
|
-
* 4. Client calls createMediaAsset to save the metadata with the storageId
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { v } from "convex/values";
|
|
15
|
-
import { mutation } from "./_generated/server.js";
|
|
16
|
-
|
|
17
|
-
// =============================================================================
|
|
18
|
-
// Constants
|
|
19
|
-
// =============================================================================
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Default maximum file size in bytes (50 MB).
|
|
23
|
-
* This is a reasonable default that can be overridden per-request.
|
|
24
|
-
*/
|
|
25
|
-
const DEFAULT_MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Maximum allowed file size in bytes (500 MB).
|
|
29
|
-
* This is the absolute upper limit to prevent abuse.
|
|
30
|
-
*/
|
|
31
|
-
const ABSOLUTE_MAX_FILE_SIZE = 500 * 1024 * 1024;
|
|
32
|
-
|
|
33
|
-
// =============================================================================
|
|
34
|
-
// Generate Upload URL Mutation
|
|
35
|
-
// =============================================================================
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Arguments for generating an upload URL.
|
|
39
|
-
*/
|
|
40
|
-
const generateUploadUrlArgs = v.object({
|
|
41
|
-
/**
|
|
42
|
-
* Optional maximum file size in bytes for the upload.
|
|
43
|
-
* This is a client-side hint that should be validated when creating the media asset.
|
|
44
|
-
* Default: 50 MB, Maximum: 500 MB
|
|
45
|
-
*/
|
|
46
|
-
maxFileSize: v.optional(v.number()),
|
|
47
|
-
/**
|
|
48
|
-
* Optional array of allowed MIME types for the upload.
|
|
49
|
-
* Supports patterns like "image/*" for all image types.
|
|
50
|
-
* This is a client-side hint that should be validated when creating the media asset.
|
|
51
|
-
*/
|
|
52
|
-
allowedMimeTypes: v.optional(v.array(v.string())),
|
|
53
|
-
/**
|
|
54
|
-
* Optional user ID for audit logging.
|
|
55
|
-
* Can be used to track who initiated the upload.
|
|
56
|
-
*/
|
|
57
|
-
requestedBy: v.optional(v.string()),
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Return type for the generateUploadUrl mutation.
|
|
62
|
-
*/
|
|
63
|
-
const uploadUrlResultDoc = v.object({
|
|
64
|
-
/** The temporary upload URL. Valid for 1 hour. */
|
|
65
|
-
uploadUrl: v.string(),
|
|
66
|
-
/**
|
|
67
|
-
* Expiration timestamp in milliseconds since epoch.
|
|
68
|
-
* The URL becomes invalid after this time.
|
|
69
|
-
*/
|
|
70
|
-
expiresAt: v.number(),
|
|
71
|
-
/**
|
|
72
|
-
* Maximum file size in bytes that will be accepted.
|
|
73
|
-
* Client should validate file size before uploading.
|
|
74
|
-
*/
|
|
75
|
-
maxFileSize: v.number(),
|
|
76
|
-
/**
|
|
77
|
-
* Allowed MIME types for the upload (if specified).
|
|
78
|
-
* Client should validate file type before uploading.
|
|
79
|
-
*/
|
|
80
|
-
allowedMimeTypes: v.optional(v.array(v.string())),
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Mutation to generate a temporary upload URL for client-side file uploads.
|
|
85
|
-
*
|
|
86
|
-
* This mutation creates a short-lived URL that allows clients to upload files
|
|
87
|
-
* directly to Convex's file storage. The URL expires after 1 hour.
|
|
88
|
-
*
|
|
89
|
-
* The upload flow works as follows:
|
|
90
|
-
* 1. Call this mutation to get a temporary upload URL
|
|
91
|
-
* 2. POST the file to the URL with Content-Type header set to the file's MIME type
|
|
92
|
-
* 3. The response contains a `storageId` that references the uploaded file
|
|
93
|
-
* 4. Call createMediaAsset mutation to save metadata and link the storageId
|
|
94
|
-
*
|
|
95
|
-
* @param maxFileSize - Optional maximum file size in bytes (default: 50 MB, max: 500 MB)
|
|
96
|
-
* @param allowedMimeTypes - Optional array of allowed MIME type patterns (e.g., ["image/*", "video/mp4"])
|
|
97
|
-
* @param requestedBy - Optional user ID for audit purposes
|
|
98
|
-
*
|
|
99
|
-
* @returns An object containing the upload URL, expiration time, and constraints
|
|
100
|
-
*
|
|
101
|
-
* @example
|
|
102
|
-
* ```typescript
|
|
103
|
-
* // Basic usage - generate URL with defaults
|
|
104
|
-
* const { uploadUrl, expiresAt, maxFileSize } = await ctx.runMutation(
|
|
105
|
-
* api.mediaUploadMutations.generateUploadUrl,
|
|
106
|
-
* {}
|
|
107
|
-
* );
|
|
108
|
-
*
|
|
109
|
-
* // With size limit - for avatar uploads
|
|
110
|
-
* const result = await ctx.runMutation(
|
|
111
|
-
* api.mediaUploadMutations.generateUploadUrl,
|
|
112
|
-
* { maxFileSize: 5 * 1024 * 1024 } // 5 MB limit
|
|
113
|
-
* );
|
|
114
|
-
*
|
|
115
|
-
* // With MIME type restrictions - for image gallery
|
|
116
|
-
* const result = await ctx.runMutation(
|
|
117
|
-
* api.mediaUploadMutations.generateUploadUrl,
|
|
118
|
-
* {
|
|
119
|
-
* maxFileSize: 10 * 1024 * 1024,
|
|
120
|
-
* allowedMimeTypes: ["image/jpeg", "image/png", "image/webp"],
|
|
121
|
-
* }
|
|
122
|
-
* );
|
|
123
|
-
*
|
|
124
|
-
* // Client-side upload after getting URL:
|
|
125
|
-
* const response = await fetch(uploadUrl, {
|
|
126
|
-
* method: "POST",
|
|
127
|
-
* headers: { "Content-Type": file.type },
|
|
128
|
-
* body: file,
|
|
129
|
-
* });
|
|
130
|
-
* const { storageId } = await response.json();
|
|
131
|
-
*
|
|
132
|
-
* // Then save metadata with createMediaAsset
|
|
133
|
-
* await ctx.runMutation(api.mediaMutations.createMediaAsset, {
|
|
134
|
-
* storageId,
|
|
135
|
-
* filename: file.name,
|
|
136
|
-
* mimeType: file.type,
|
|
137
|
-
* size: file.size,
|
|
138
|
-
* type: "image",
|
|
139
|
-
* });
|
|
140
|
-
* ```
|
|
141
|
-
*/
|
|
142
|
-
export const generateUploadUrl = mutation({
|
|
143
|
-
args: generateUploadUrlArgs.fields,
|
|
144
|
-
returns: uploadUrlResultDoc,
|
|
145
|
-
handler: async (ctx, args) => {
|
|
146
|
-
const { maxFileSize, allowedMimeTypes } = args;
|
|
147
|
-
|
|
148
|
-
// Validate and normalize maxFileSize
|
|
149
|
-
let effectiveMaxFileSize = DEFAULT_MAX_FILE_SIZE;
|
|
150
|
-
if (maxFileSize !== undefined) {
|
|
151
|
-
if (maxFileSize <= 0) {
|
|
152
|
-
throw new Error("maxFileSize must be a positive number");
|
|
153
|
-
}
|
|
154
|
-
if (maxFileSize > ABSOLUTE_MAX_FILE_SIZE) {
|
|
155
|
-
throw new Error(
|
|
156
|
-
`maxFileSize cannot exceed ${ABSOLUTE_MAX_FILE_SIZE} bytes (500 MB)`,
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
effectiveMaxFileSize = maxFileSize;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Validate allowedMimeTypes if provided
|
|
163
|
-
if (allowedMimeTypes !== undefined) {
|
|
164
|
-
if (allowedMimeTypes.length === 0) {
|
|
165
|
-
throw new Error("allowedMimeTypes cannot be an empty array");
|
|
166
|
-
}
|
|
167
|
-
// Validate MIME type patterns
|
|
168
|
-
for (const mimeType of allowedMimeTypes) {
|
|
169
|
-
if (!isValidMimeTypePattern(mimeType)) {
|
|
170
|
-
throw new Error(`Invalid MIME type pattern: ${mimeType}`);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Generate the upload URL using Convex's storage API
|
|
176
|
-
// The URL is valid for 1 hour from generation
|
|
177
|
-
const uploadUrl = await ctx.storage.generateUploadUrl();
|
|
178
|
-
|
|
179
|
-
// Calculate expiration time (1 hour from now)
|
|
180
|
-
const expiresAt = Date.now() + 60 * 60 * 1000;
|
|
181
|
-
|
|
182
|
-
return {
|
|
183
|
-
uploadUrl,
|
|
184
|
-
expiresAt,
|
|
185
|
-
maxFileSize: effectiveMaxFileSize,
|
|
186
|
-
allowedMimeTypes,
|
|
187
|
-
};
|
|
188
|
-
},
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// =============================================================================
|
|
192
|
-
// Helper Functions
|
|
193
|
-
// =============================================================================
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Validates a MIME type pattern.
|
|
197
|
-
*
|
|
198
|
-
* Accepts:
|
|
199
|
-
* - Full MIME types: "image/png", "video/mp4", "application/pdf"
|
|
200
|
-
* - Wildcard patterns: "image/*", "video/*", "audio/*"
|
|
201
|
-
*
|
|
202
|
-
* Per RFC 6838, MIME type names must start with a letter.
|
|
203
|
-
*
|
|
204
|
-
* @param pattern - The MIME type pattern to validate
|
|
205
|
-
* @returns True if the pattern is valid
|
|
206
|
-
*/
|
|
207
|
-
function isValidMimeTypePattern(pattern: string): boolean {
|
|
208
|
-
// Check for empty or whitespace-only strings
|
|
209
|
-
if (!pattern || pattern.trim() === "") {
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// MIME type pattern: type/subtype or type/*
|
|
214
|
-
// type: must start with letter, followed by alphanumeric, hyphens, underscores
|
|
215
|
-
// subtype: alphanumeric, hyphens, underscores, periods, plus signs, or wildcard
|
|
216
|
-
const mimeTypeRegex = /^[a-zA-Z][a-zA-Z0-9\-_]*\/(\*|[a-zA-Z0-9][a-zA-Z0-9\-_.+]*)$/;
|
|
217
|
-
return mimeTypeRegex.test(pattern);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// =============================================================================
|
|
221
|
-
// Export validators for use in other modules
|
|
222
|
-
// =============================================================================
|
|
223
|
-
|
|
224
|
-
export { generateUploadUrlArgs, uploadUrlResultDoc };
|