@nextblock-cms/db 0.22.1 → 0.22.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.
Files changed (43) hide show
  1. package/README.md +47 -47
  2. package/lib/media-actions.cjs.js +1 -1
  3. package/lib/media-actions.d.ts +13 -35
  4. package/lib/media-actions.es.js +25 -49
  5. package/lib/media-actions.test.d.ts +1 -0
  6. package/lib/media-record.cjs.js +1 -0
  7. package/lib/media-record.d.ts +46 -0
  8. package/lib/media-record.es.js +47 -0
  9. package/lib/package-validation.cjs.js +1 -1
  10. package/lib/package-validation.es.js +1 -1
  11. package/lib/secret-crypto.cjs.js +1 -1
  12. package/lib/secret-crypto.es.js +1 -0
  13. package/lib/supabase/server.cjs.js +1 -1
  14. package/lib/supabase/server.es.js +1 -0
  15. package/package.json +1 -1
  16. package/server.cjs.js +1 -1
  17. package/server.d.ts +1 -0
  18. package/server.es.js +6 -5
  19. package/supabase/migrations/02000_catchup_gen1.sql +5880 -5880
  20. package/supabase/migrations/02001_baseline_schema.sql +2734 -2734
  21. package/supabase/migrations/02002_baseline_constraints_and_indexes.sql +1262 -1262
  22. package/supabase/migrations/02003_baseline_security_and_grants.sql +1577 -1577
  23. package/supabase/migrations/02004_baseline_seed.sql +565 -565
  24. package/supabase/migrations/02005_home_live_demo_promo_cadence_15min.sql +53 -53
  25. package/supabase/migrations/02006_home_marketing_contrast.sql +56 -56
  26. package/supabase/migrations/02007_home_pillar_caption_contrast.sql +44 -44
  27. package/supabase/migrations/02008_home_fr_parity.sql +89 -89
  28. package/supabase/migrations/02009_fr_cortex_posts.sql +67 -67
  29. package/supabase/migrations/02010_shop_hero_redesign.sql +72 -72
  30. package/supabase/migrations/02011_drop_backdrop_blur_on_pages.sql +26 -26
  31. package/supabase/migrations/02012_drop_variant_backdrop_blur.sql +17 -17
  32. package/supabase/migrations/02013_advisor_rls_and_trigger_grants.sql +102 -102
  33. package/supabase/migrations/02014_package_activations_staff_read.sql +18 -18
  34. package/supabase/migrations/02018_install_paths_and_seed_copy_accuracy.sql +1820 -1820
  35. package/supabase/migrations/02019_open_handed_licensing_and_mcp_clients.sql +448 -448
  36. package/supabase/migrations/02020_commerce_product_accuracy.sql +93 -93
  37. package/supabase/migrations/02021_profiles_staff_read_and_role_guard.sql +362 -362
  38. package/supabase/migrations/02022_security_hardening_writer_boundary_and_aal.sql +504 -504
  39. package/supabase/migrations/02024_advisor_trigger_grants_and_pg_net_schema.sql +113 -0
  40. package/supabase/migrations/02025_api_role_grant_hardening.sql +66 -0
  41. package/supabase/migrations/02026_authenticated_write_grant_hardening.sql +91 -0
  42. package/supabase/migrations/02027_api_role_select_grant_hardening.sql +150 -0
  43. package/supabase/migrations/02028_writer_settings_allowlist_email_factor_aal_and_media_keys.sql +284 -0
package/README.md CHANGED
@@ -1,47 +1,47 @@
1
- # @nextblock-cms/db
2
-
3
- The database layer of [NextBlock](https://github.com/nextblock-cms/nextblock), the open-core CMS
4
- for Next.js and Supabase: Supabase clients for each trust level, the generated `Database` types,
5
- secret encryption, and the premium-package license check. It also ships the NextBlock database
6
- migrations.
7
-
8
- Projects created with `npm create nextblock@latest` already depend on it. It is built for
9
- NextBlock projects (Next.js 16, React 19, `@supabase/ssr`) rather than as a general-purpose
10
- library.
11
-
12
- ```bash
13
- npm install @nextblock-cms/db
14
- ```
15
-
16
- ## Entry points
17
-
18
- | Import | Use it from | What it holds |
19
- | :-- | :-- | :-- |
20
- | `@nextblock-cms/db` | client | The browser Supabase client (`createClient`), the `Database` types, and client-side profile and language lookups |
21
- | `@nextblock-cms/db/server` | server only | `createClient()` scoped to the request cookies, `getSsgSupabaseClient()` for public reads, `getServiceRoleSupabaseClient()` for admin work only (it bypasses Row Level Security), `verifyPackageOnline()`, secret encryption and config resolution |
22
- | `@nextblock-cms/db/secrets` | server only | Secret encryption (`encryptSecret`, `decryptSecret`) and config resolution, without the Supabase clients |
23
- | `@nextblock-cms/db/types` | types only | The generated `Database` types |
24
-
25
- Pick the server client by trust level. Use the service-role client only in code that has
26
- already checked the caller's role.
27
-
28
- ## Environment
29
-
30
- The clients read `NEXT_PUBLIC_SUPABASE_URL` or `SUPABASE_URL`, the publishable (anon) key under
31
- either its `NEXT_PUBLIC_` or its plain name, and, for the service-role client,
32
- `SUPABASE_SERVICE_ROLE_KEY` or `SUPABASE_SECRET_KEY`. The alternative names are the ones the
33
- Vercel Supabase integration injects.
34
-
35
- ## Migrations
36
-
37
- The package includes `supabase/` with the NextBlock migrations. `npm run update` in a NextBlock
38
- project copies them into the project's `supabase/migrations` and applies the pending ones.
39
-
40
- ## Documentation
41
-
42
- - [Database and auth](https://github.com/nextblock-cms/nextblock/blob/master/docs/04-DATABASE-AND-AUTH.md)
43
- - [Staying up to date](https://github.com/nextblock-cms/nextblock/blob/master/docs/13-STAYING-UP-TO-DATE.md)
44
-
45
- ## License
46
-
47
- AGPL-3.0-or-later.
1
+ # @nextblock-cms/db
2
+
3
+ The database layer of [NextBlock](https://github.com/nextblock-cms/nextblock), the open-core CMS
4
+ for Next.js and Supabase: Supabase clients for each trust level, the generated `Database` types,
5
+ secret encryption, and the premium-package license check. It also ships the NextBlock database
6
+ migrations.
7
+
8
+ Projects created with `npm create nextblock@latest` already depend on it. It is built for
9
+ NextBlock projects (Next.js 16, React 19, `@supabase/ssr`) rather than as a general-purpose
10
+ library.
11
+
12
+ ```bash
13
+ npm install @nextblock-cms/db
14
+ ```
15
+
16
+ ## Entry points
17
+
18
+ | Import | Use it from | What it holds |
19
+ | :-- | :-- | :-- |
20
+ | `@nextblock-cms/db` | client | The browser Supabase client (`createClient`), the `Database` types, and client-side profile and language lookups |
21
+ | `@nextblock-cms/db/server` | server only | `createClient()` scoped to the request cookies, `getSsgSupabaseClient()` for public reads, `getServiceRoleSupabaseClient()` for admin work only (it bypasses Row Level Security), `verifyPackageOnline()`, secret encryption and config resolution |
22
+ | `@nextblock-cms/db/secrets` | server only | Secret encryption (`encryptSecret`, `decryptSecret`) and config resolution, without the Supabase clients |
23
+ | `@nextblock-cms/db/types` | types only | The generated `Database` types |
24
+
25
+ Pick the server client by trust level. Use the service-role client only in code that has
26
+ already checked the caller's role.
27
+
28
+ ## Environment
29
+
30
+ The clients read `NEXT_PUBLIC_SUPABASE_URL` or `SUPABASE_URL`, the publishable (anon) key under
31
+ either its `NEXT_PUBLIC_` or its plain name, and, for the service-role client,
32
+ `SUPABASE_SERVICE_ROLE_KEY` or `SUPABASE_SECRET_KEY`. The alternative names are the ones the
33
+ Vercel Supabase integration injects.
34
+
35
+ ## Migrations
36
+
37
+ The package includes `supabase/` with the NextBlock migrations. `npm run update` in a NextBlock
38
+ project copies them into the project's `supabase/migrations` and applies the pending ones.
39
+
40
+ ## Documentation
41
+
42
+ - [Database and auth](https://github.com/nextblock-cms/nextblock/blob/master/docs/04-DATABASE-AND-AUTH.md)
43
+ - [Staying up to date](https://github.com/nextblock-cms/nextblock/blob/master/docs/13-STAYING-UP-TO-DATE.md)
44
+
45
+ ## License
46
+
47
+ AGPL-3.0-or-later.
@@ -1 +1 @@
1
- "use server";const e=require("./supabase/server.cjs.js");let t=require("next/cache"),n=require("@nextblock-cms/utils/server");async function r(r,i){let a=r.actorUserId,o=a?e.getServiceRoleSupabaseClient():e.createClient(),s;if(a)s=a;else{let{data:{user:e},error:t}=await o.auth.getUser();if(t||!e)return i?{error:`User not authenticated for media record.`}:(0,n.encodedRedirect)(`error`,`/cms/media`,`User not authenticated for media record.`);s=e.id}let{data:c}=await o.from(`profiles`).select(`role`).eq(`id`,s).single();if(!c||![`ADMIN`,`WRITER`].includes(c.role))return i?{error:`Forbidden: Insufficient permissions to record media.`}:(0,n.encodedRedirect)(`error`,`/cms/media`,`Forbidden: Insufficient permissions to record media.`);let l=r.r2Variants.find(e=>e.variantLabel===`original_avif`)||r.r2Variants.find(e=>e.variantLabel===`xlarge_avif`)||r.r2Variants[0]||r.originalImageDetails;l||=r.originalImageDetails||{objectKey:r.r2OriginalKey,url:``,width:0,height:0,fileType:`application/octet-stream`,sizeBytes:0,variantLabel:`fallback_original`};let u=[...r.originalImageDetails&&r.originalImageDetails.objectKey!==l.objectKey?[r.originalImageDetails]:[],...r.r2Variants].filter((e,t,n)=>t===n.findIndex(t=>t.objectKey===e.objectKey)),d=r.description??(l.fileType?.startsWith(`image/`)||r.originalImageDetails?.fileType?.startsWith(`image/`)?(e=>{let t=e.lastIndexOf(`.`);return(t>0?e.substring(0,t):e).replace(/[-+_\\]+/g,` `).replace(/\s+/g,` `).trim().replace(/\b\w+/g,e=>e.charAt(0).toUpperCase()+e.slice(1))})(r.fileName):null),f={uploader_id:s,file_name:r.fileName,object_key:l.objectKey,file_path:l.objectKey,folder:(()=>{let e=l.objectKey.match(/^(.*\/)?.*$/);return e&&e[1]?e[1]:null})(),file_type:l.fileType,size_bytes:l.sizeBytes,description:d,width:l.width,height:l.height,variants:u,blur_data_url:r.blurDataUrl||null},{data:p,error:m}=await o.from(`media`).insert(f).select().single();if(m)return console.error(`Error recording media upload:`,m),i?{error:`Failed to record media: ${m.message}`}:(0,n.encodedRedirect)(`error`,`/cms/media`,`Failed to record media: ${m.message}`);if((0,t.revalidatePath)(`/cms/media`),i)return{success:!0,data:p};(0,n.encodedRedirect)(`success`,`/cms/media`,`Media recorded successfully.`)}exports.recordMediaUpload=r;
1
+ "use server";const e=require("./supabase/server.cjs.js"),t=require("./media-record.cjs.js");require("server-only");let n=require("@nextblock-cms/utils/server");var r=Symbol.for(`nextblock.cms.secondFactorGate`);async function i(e,t){let n=globalThis[r];if(typeof n==`function`)return!!await n();let{data:i}=await e.from(`user_security_settings`).select(`mfa_enabled, mfa_type`).eq(`user_id`,t).maybeSingle();if(!i?.mfa_enabled||!i?.mfa_type)return!0;if(i.mfa_type===`totp`){let{data:t}=await e.auth.mfa.getAuthenticatorAssuranceLevel();return t?.currentLevel===`aal2`}return!1}async function a(r,a){let o=e.createClient(),{data:{user:s},error:c}=await o.auth.getUser();if(c||!s)return a?{error:`User not authenticated for media record.`}:(0,n.encodedRedirect)(`error`,`/cms/media`,`User not authenticated for media record.`);let{data:l}=await o.from(`profiles`).select(`role`).eq(`id`,s.id).single();if(!l||![`ADMIN`,`WRITER`].includes(l.role)||!await i(o,s.id))return a?{error:`Forbidden: Insufficient permissions to record media.`}:(0,n.encodedRedirect)(`error`,`/cms/media`,`Forbidden: Insufficient permissions to record media.`);let u=await t.insertMediaRecord(o,s.id,r);if(`error`in u)return a?u:(0,n.encodedRedirect)(`error`,`/cms/media`,u.error);if(a)return u;(0,n.encodedRedirect)(`success`,`/cms/media`,`Media recorded successfully.`)}exports.recordMediaUpload=a;
@@ -1,35 +1,13 @@
1
- import { Database } from './supabase/types';
2
- type Media = Database['public']['Tables']['media']['Row'];
3
- export interface ImageVariant {
4
- objectKey: string;
5
- url: string;
6
- width: number;
7
- height: number;
8
- fileType: string;
9
- sizeBytes: number;
10
- variantLabel: string;
11
- }
12
- export declare function recordMediaUpload(payload: {
13
- fileName: string;
14
- description?: string;
15
- r2OriginalKey: string;
16
- r2Variants: ImageVariant[];
17
- originalImageDetails: ImageVariant;
18
- blurDataUrl?: string;
19
- /**
20
- * Uploader for callers that have no cookie session — the MCP server, which
21
- * authenticates by bearer token instead. When set, the row is written with the
22
- * service-role client and attributed to this user rather than to `auth.getUser()`.
23
- *
24
- * This grants no new authority: the role check below still runs against the
25
- * supplied id, so a non-ADMIN/WRITER actor is rejected exactly as a cookie
26
- * session would be. The caller is responsible for having authenticated them.
27
- */
28
- actorUserId?: string;
29
- }, returnJustData?: boolean): Promise<{
30
- success: true;
31
- data: Media;
32
- } | {
33
- error: string;
34
- } | void>;
35
- export {};
1
+ import { MediaRecordResult, MediaUploadPayload } from './media-record';
2
+ export type { ImageVariant, MediaRecordResult, MediaUploadPayload } from './media-record';
3
+ /**
4
+ * Record an upload as the signed-in ADMIN or WRITER.
5
+ *
6
+ * A server action is a public POST endpoint, so the uploader is always the cookie
7
+ * session's user, never anything in the payload. Until 2026-10-21 the payload could name
8
+ * one (`actorUserId`, for the MCP server) and the session cross-check ran only when a
9
+ * session existed, so a cookieless POST naming an admin's id recorded media as that admin
10
+ * with the service role. Server routes without a session use `recordMediaUploadAsActor`
11
+ * (`@nextblock-cms/db/server`), which is not a server action.
12
+ */
13
+ export declare function recordMediaUpload(payload: MediaUploadPayload, returnJustData?: boolean): Promise<MediaRecordResult | void>;
@@ -1,54 +1,30 @@
1
1
  "use server";
2
- import { createClient as e, getServiceRoleSupabaseClient as t } from "./supabase/server.es.js";
3
- import { revalidatePath as n } from "next/cache";
4
- import { encodedRedirect as r } from "@nextblock-cms/utils/server";
2
+ import { createClient as e } from "./supabase/server.es.js";
3
+ import { insertMediaRecord as t } from "./media-record.es.js";
4
+ import "server-only";
5
+ import { encodedRedirect as n } from "@nextblock-cms/utils/server";
5
6
  //#region src/lib/media-actions.ts
6
- async function i(i, a) {
7
- let o = i.actorUserId, s = o ? t() : e(), c;
8
- if (o) c = o;
9
- else {
10
- let { data: { user: e }, error: t } = await s.auth.getUser();
11
- if (t || !e) return a ? { error: "User not authenticated for media record." } : r("error", "/cms/media", "User not authenticated for media record.");
12
- c = e.id;
7
+ var r = Symbol.for("nextblock.cms.secondFactorGate");
8
+ async function i(e, t) {
9
+ let n = globalThis[r];
10
+ if (typeof n == "function") return !!await n();
11
+ let { data: i } = await e.from("user_security_settings").select("mfa_enabled, mfa_type").eq("user_id", t).maybeSingle();
12
+ if (!i?.mfa_enabled || !i?.mfa_type) return !0;
13
+ if (i.mfa_type === "totp") {
14
+ let { data: t } = await e.auth.mfa.getAuthenticatorAssuranceLevel();
15
+ return t?.currentLevel === "aal2";
13
16
  }
14
- let { data: l } = await s.from("profiles").select("role").eq("id", c).single();
15
- if (!l || !["ADMIN", "WRITER"].includes(l.role)) return a ? { error: "Forbidden: Insufficient permissions to record media." } : r("error", "/cms/media", "Forbidden: Insufficient permissions to record media.");
16
- let u = i.r2Variants.find((e) => e.variantLabel === "original_avif") || i.r2Variants.find((e) => e.variantLabel === "xlarge_avif") || i.r2Variants[0] || i.originalImageDetails;
17
- u ||= i.originalImageDetails || {
18
- objectKey: i.r2OriginalKey,
19
- url: "",
20
- width: 0,
21
- height: 0,
22
- fileType: "application/octet-stream",
23
- sizeBytes: 0,
24
- variantLabel: "fallback_original"
25
- };
26
- let d = [...i.originalImageDetails && i.originalImageDetails.objectKey !== u.objectKey ? [i.originalImageDetails] : [], ...i.r2Variants].filter((e, t, n) => t === n.findIndex((t) => t.objectKey === e.objectKey)), f = i.description ?? (u.fileType?.startsWith("image/") || i.originalImageDetails?.fileType?.startsWith("image/") ? ((e) => {
27
- let t = e.lastIndexOf(".");
28
- return (t > 0 ? e.substring(0, t) : e).replace(/[-+_\\]+/g, " ").replace(/\s+/g, " ").trim().replace(/\b\w+/g, (e) => e.charAt(0).toUpperCase() + e.slice(1));
29
- })(i.fileName) : null), p = {
30
- uploader_id: c,
31
- file_name: i.fileName,
32
- object_key: u.objectKey,
33
- file_path: u.objectKey,
34
- folder: (() => {
35
- let e = u.objectKey.match(/^(.*\/)?.*$/);
36
- return e && e[1] ? e[1] : null;
37
- })(),
38
- file_type: u.fileType,
39
- size_bytes: u.sizeBytes,
40
- description: f,
41
- width: u.width,
42
- height: u.height,
43
- variants: d,
44
- blur_data_url: i.blurDataUrl || null
45
- }, { data: m, error: h } = await s.from("media").insert(p).select().single();
46
- if (h) return console.error("Error recording media upload:", h), a ? { error: `Failed to record media: ${h.message}` } : r("error", "/cms/media", `Failed to record media: ${h.message}`);
47
- if (n("/cms/media"), a) return {
48
- success: !0,
49
- data: m
50
- };
51
- r("success", "/cms/media", "Media recorded successfully.");
17
+ return !1;
18
+ }
19
+ async function a(r, a) {
20
+ let o = e(), { data: { user: s }, error: c } = await o.auth.getUser();
21
+ if (c || !s) return a ? { error: "User not authenticated for media record." } : n("error", "/cms/media", "User not authenticated for media record.");
22
+ let { data: l } = await o.from("profiles").select("role").eq("id", s.id).single();
23
+ if (!l || !["ADMIN", "WRITER"].includes(l.role) || !await i(o, s.id)) return a ? { error: "Forbidden: Insufficient permissions to record media." } : n("error", "/cms/media", "Forbidden: Insufficient permissions to record media.");
24
+ let u = await t(o, s.id, r);
25
+ if ("error" in u) return a ? u : n("error", "/cms/media", u.error);
26
+ if (a) return u;
27
+ n("success", "/cms/media", "Media recorded successfully.");
52
28
  }
53
29
  //#endregion
54
- export { i as recordMediaUpload };
30
+ export { a as recordMediaUpload };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ const e=require("./supabase/server.cjs.js");require("server-only");let t=require("next/cache");var n=[`ADMIN`,`WRITER`];async function r(e,n,r){let i=r.r2Variants.find(e=>e.variantLabel===`original_avif`)||r.r2Variants.find(e=>e.variantLabel===`xlarge_avif`)||r.r2Variants[0]||r.originalImageDetails;i||=r.originalImageDetails||{objectKey:r.r2OriginalKey,url:``,width:0,height:0,fileType:`application/octet-stream`,sizeBytes:0,variantLabel:`fallback_original`};let a=[...r.originalImageDetails&&r.originalImageDetails.objectKey!==i.objectKey?[r.originalImageDetails]:[],...r.r2Variants].filter((e,t,n)=>t===n.findIndex(t=>t.objectKey===e.objectKey)),o=r.description??(i.fileType?.startsWith(`image/`)||r.originalImageDetails?.fileType?.startsWith(`image/`)?(e=>{let t=e.lastIndexOf(`.`);return(t>0?e.substring(0,t):e).replace(/[-+_\\]+/g,` `).replace(/\s+/g,` `).trim().replace(/\b\w+/g,e=>e.charAt(0).toUpperCase()+e.slice(1))})(r.fileName):null),s={uploader_id:n,file_name:r.fileName,object_key:i.objectKey,file_path:i.objectKey,folder:(()=>{let e=i.objectKey.match(/^(.*\/)?.*$/);return e&&e[1]?e[1]:null})(),file_type:i.fileType,size_bytes:i.sizeBytes,description:o,width:i.width,height:i.height,variants:a,blur_data_url:r.blurDataUrl||null},{data:c,error:l}=await e.from(`media`).insert(s).select().single();return l?(console.error(`Error recording media upload:`,l),{error:`Failed to record media: ${l.message}`}):((0,t.revalidatePath)(`/cms/media`),{success:!0,data:c})}async function i(t,i){let a=e.getServiceRoleSupabaseClient(),{data:o}=await a.from(`profiles`).select(`role`).eq(`id`,i).maybeSingle();return!o||!n.includes(o.role)?{error:`Forbidden: Insufficient permissions to record media.`}:r(a,i,t)}exports.insertMediaRecord=r,exports.recordMediaUploadAsActor=i;
@@ -0,0 +1,46 @@
1
+ import { Database } from './supabase/types';
2
+ type Media = Database['public']['Tables']['media']['Row'];
3
+ export interface ImageVariant {
4
+ objectKey: string;
5
+ url: string;
6
+ width: number;
7
+ height: number;
8
+ fileType: string;
9
+ sizeBytes: number;
10
+ variantLabel: string;
11
+ }
12
+ export type MediaUploadPayload = {
13
+ fileName: string;
14
+ description?: string;
15
+ r2OriginalKey: string;
16
+ r2Variants: ImageVariant[];
17
+ originalImageDetails: ImageVariant;
18
+ blurDataUrl?: string;
19
+ };
20
+ export type MediaRecordResult = {
21
+ success: true;
22
+ data: Media;
23
+ } | {
24
+ error: string;
25
+ };
26
+ type MediaInsertClient = {
27
+ from: (table: string) => any;
28
+ };
29
+ /**
30
+ * Insert the `media` row for an upload, attributed to `uploaderId`. Takes the payload's
31
+ * known fields only. The caller has already established who `uploaderId` is: the cookie
32
+ * session (`recordMediaUpload`) or an authenticated server route (`recordMediaUploadAsActor`).
33
+ */
34
+ export declare function insertMediaRecord(supabase: MediaInsertClient, uploaderId: string, payload: MediaUploadPayload): Promise<MediaRecordResult>;
35
+ /**
36
+ * Record an upload for a server route that has no cookie session and has already
37
+ * authenticated its caller: `/api/mcp` (bearer token) and `/api/ai/*`. Writes with the
38
+ * service role, after re-reading the actor's role.
39
+ *
40
+ * Deliberately NOT a server action (no `'use server'`, and not exported from the
41
+ * client-safe `@nextblock-cms/db` entry): until 2026-10-21 `recordMediaUpload` accepted
42
+ * this actor id from its payload, so a cookieless POST naming an admin's id (public via
43
+ * `posts.author_id`) recorded media as that admin.
44
+ */
45
+ export declare function recordMediaUploadAsActor(payload: MediaUploadPayload, actorUserId: string): Promise<MediaRecordResult>;
46
+ export {};
@@ -0,0 +1,47 @@
1
+ import { getServiceRoleSupabaseClient as e } from "./supabase/server.es.js";
2
+ import "server-only";
3
+ import { revalidatePath as t } from "next/cache";
4
+ //#region src/lib/media-record.ts
5
+ var n = ["ADMIN", "WRITER"];
6
+ async function r(e, n, r) {
7
+ let i = r.r2Variants.find((e) => e.variantLabel === "original_avif") || r.r2Variants.find((e) => e.variantLabel === "xlarge_avif") || r.r2Variants[0] || r.originalImageDetails;
8
+ i ||= r.originalImageDetails || {
9
+ objectKey: r.r2OriginalKey,
10
+ url: "",
11
+ width: 0,
12
+ height: 0,
13
+ fileType: "application/octet-stream",
14
+ sizeBytes: 0,
15
+ variantLabel: "fallback_original"
16
+ };
17
+ let a = [...r.originalImageDetails && r.originalImageDetails.objectKey !== i.objectKey ? [r.originalImageDetails] : [], ...r.r2Variants].filter((e, t, n) => t === n.findIndex((t) => t.objectKey === e.objectKey)), o = r.description ?? (i.fileType?.startsWith("image/") || r.originalImageDetails?.fileType?.startsWith("image/") ? ((e) => {
18
+ let t = e.lastIndexOf(".");
19
+ return (t > 0 ? e.substring(0, t) : e).replace(/[-+_\\]+/g, " ").replace(/\s+/g, " ").trim().replace(/\b\w+/g, (e) => e.charAt(0).toUpperCase() + e.slice(1));
20
+ })(r.fileName) : null), s = {
21
+ uploader_id: n,
22
+ file_name: r.fileName,
23
+ object_key: i.objectKey,
24
+ file_path: i.objectKey,
25
+ folder: (() => {
26
+ let e = i.objectKey.match(/^(.*\/)?.*$/);
27
+ return e && e[1] ? e[1] : null;
28
+ })(),
29
+ file_type: i.fileType,
30
+ size_bytes: i.sizeBytes,
31
+ description: o,
32
+ width: i.width,
33
+ height: i.height,
34
+ variants: a,
35
+ blur_data_url: r.blurDataUrl || null
36
+ }, { data: c, error: l } = await e.from("media").insert(s).select().single();
37
+ return l ? (console.error("Error recording media upload:", l), { error: `Failed to record media: ${l.message}` }) : (t("/cms/media"), {
38
+ success: !0,
39
+ data: c
40
+ });
41
+ }
42
+ async function i(t, i) {
43
+ let a = e(), { data: o } = await a.from("profiles").select("role").eq("id", i).maybeSingle();
44
+ return !o || !n.includes(o.role) ? { error: "Forbidden: Insufficient permissions to record media." } : r(a, i, t);
45
+ }
46
+ //#endregion
47
+ export { r as insertMediaRecord, i as recordMediaUploadAsActor };
@@ -1 +1 @@
1
- const e=require("./supabase/server.cjs.js");let t=require("@supabase/supabase-js"),n=require("next/cache");require("server-only");var r=`package-activation`;function i(e){if(typeof e!=`string`||!e.trim())return null;let t=e.trim(),n=/(?:z|[+-]\d{2}:?\d{2})$/i.test(t),r=Date.parse(n?t:`${t.replace(` `,`T`)}Z`);return Number.isFinite(r)?r:null}function a(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e,n=t.nextblock&&typeof t.nextblock==`object`&&!Array.isArray(t.nextblock)?t.nextblock:null,r=[n?.expiration,n?.trial_ends_at,t.expiration].map(i).filter(e=>e!==null);return r.length>0?Math.min(...r):null}function o(e,t=Date.now()){if(e.status!==`active`)return!1;let n=a(e.meta);return n===null||n>t}async function s(e,t){try{let{data:n,error:r}=await t.from(`package_activations`).select(`status, meta`).eq(`package_id`,e).eq(`status`,`active`).limit(5);return r||!Array.isArray(n)?!1:n.some(e=>o(e))}catch(t){return console.error(`Error verifying package ${e}:`,t),!1}}var c=(0,n.unstable_cache)(async e=>{let n=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,r=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY||process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY||process.env.SUPABASE_ANON_KEY||process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY||process.env.SUPABASE_PUBLISHABLE_KEY;return!n||!r?!1:s(e,(0,t.createClient)(n,r,{auth:{persistSession:!1,autoRefreshToken:!1,detectSessionInUrl:!1}}))},[`package-activation`],{revalidate:60,tags:[r]});async function l(t,n){if(n)return s(t,n);let r=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,i=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY||process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY||process.env.SUPABASE_ANON_KEY||process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY||process.env.SUPABASE_PUBLISHABLE_KEY;return r&&i?c(t):s(t,await e.createClient())}exports.PACKAGE_ACTIVATION_CACHE_TAG=r,exports.isPackageActivationRowValid=o,exports.resolvePackageActivationExpiry=a,exports.verifyPackageOnline=l;
1
+ const e=require("./supabase/server.cjs.js");require("server-only");let t=require("@supabase/supabase-js"),n=require("next/cache");var r=`package-activation`;function i(e){if(typeof e!=`string`||!e.trim())return null;let t=e.trim(),n=/(?:z|[+-]\d{2}:?\d{2})$/i.test(t),r=Date.parse(n?t:`${t.replace(` `,`T`)}Z`);return Number.isFinite(r)?r:null}function a(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e,n=t.nextblock&&typeof t.nextblock==`object`&&!Array.isArray(t.nextblock)?t.nextblock:null,r=[n?.expiration,n?.trial_ends_at,t.expiration].map(i).filter(e=>e!==null);return r.length>0?Math.min(...r):null}function o(e,t=Date.now()){if(e.status!==`active`)return!1;let n=a(e.meta);return n===null||n>t}async function s(e,t){try{let{data:n,error:r}=await t.from(`package_activations`).select(`status, meta`).eq(`package_id`,e).eq(`status`,`active`).limit(5);return r||!Array.isArray(n)?!1:n.some(e=>o(e))}catch(t){return console.error(`Error verifying package ${e}:`,t),!1}}var c=(0,n.unstable_cache)(async e=>{let n=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,r=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY||process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY||process.env.SUPABASE_ANON_KEY||process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY||process.env.SUPABASE_PUBLISHABLE_KEY;return!n||!r?!1:s(e,(0,t.createClient)(n,r,{auth:{persistSession:!1,autoRefreshToken:!1,detectSessionInUrl:!1}}))},[`package-activation`],{revalidate:60,tags:[r]});async function l(t,n){if(n)return s(t,n);let r=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,i=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY||process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY||process.env.SUPABASE_ANON_KEY||process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY||process.env.SUPABASE_PUBLISHABLE_KEY;return r&&i?c(t):s(t,await e.createClient())}exports.PACKAGE_ACTIVATION_CACHE_TAG=r,exports.isPackageActivationRowValid=o,exports.resolvePackageActivationExpiry=a,exports.verifyPackageOnline=l;
@@ -1,7 +1,7 @@
1
1
  import { createClient as e } from "./supabase/server.es.js";
2
+ import "server-only";
2
3
  import { createClient as t } from "@supabase/supabase-js";
3
4
  import { unstable_cache as n } from "next/cache";
4
- import "server-only";
5
5
  //#region src/lib/package-validation.ts
6
6
  var r = "package-activation";
7
7
  function i(e) {
@@ -1 +1 @@
1
- let e=require("node:crypto");var t=`aes-256-gcm`,n=1;function r(t){let n=t.trim();if(!n)throw Error(`A non-empty encryption secret is required to manage stored secrets.`);return(0,e.createHash)(`sha256`).update(n).digest()}function i(e){if(!e||typeof e!=`object`)return!1;let t=e;return t.algorithm===`aes-256-gcm`&&t.version===1&&typeof t.authTag==`string`&&typeof t.ciphertext==`string`&&typeof t.iv==`string`}function a(e){if(!i(e))throw Error(`Invalid encrypted secret payload.`);let t=e;return{algorithm:t.algorithm,authTag:t.authTag,ciphertext:t.ciphertext,iv:t.iv,last4:typeof t.last4==`string`?t.last4:``,updatedAt:typeof t.updatedAt==`string`?t.updatedAt:``,version:t.version}}function o(n){let i=n.value.trim();if(!i)throw Error(`A non-empty value is required to encrypt a secret.`);let a=r(n.encryptionSecret),o=(0,e.randomBytes)(12),s=(0,e.createCipheriv)(t,a,o),c=Buffer.concat([s.update(i,`utf8`),s.final()]);return{algorithm:t,authTag:s.getAuthTag().toString(`base64`),ciphertext:c.toString(`base64`),iv:o.toString(`base64`),last4:i.slice(-4),updatedAt:(n.now??new Date).toISOString(),version:1}}function s(n){let i=a(n.envelope),o=r(n.encryptionSecret);try{let n=(0,e.createDecipheriv)(t,o,Buffer.from(i.iv,`base64`));return n.setAuthTag(Buffer.from(i.authTag,`base64`)),Buffer.concat([n.update(Buffer.from(i.ciphertext,`base64`)),n.final()]).toString(`utf8`)}catch{throw Error(`Failed to decrypt stored secret.`)}}function c(e){let t=(e??``).trim();return t?`•••• ${t}`:`Stored secret`}function l(e){if(!i(e))return{hasStoredValue:!1,last4:null,maskedValue:null,updatedAt:null};let t=e,n=typeof t.last4==`string`&&t.last4?t.last4:null;return{hasStoredValue:!0,last4:n,maskedValue:c(n),updatedAt:typeof t.updatedAt==`string`&&t.updatedAt?t.updatedAt:null}}var u=`nextblock-secret-encryption-key-v1`;function d(){let t=process.env.SUPABASE_SERVICE_ROLE_KEY??process.env.SUPABASE_SECRET_KEY;return typeof t!=`string`||!t.trim()?null:(0,e.createHmac)(`sha256`,t.trim()).update(u).digest(`hex`)}function f(){let e=[],t=t=>{let n=typeof t==`string`?t.trim():``;n&&!e.includes(n)&&e.push(n)};return t(process.env.NEXTBLOCK_ENCRYPTION_KEY),t(process.env.CORTEX_AI_ENCRYPTION_KEY),t(d()),e}function p(){return f()[0]??null}function m(){return p()!==null}function h(){let e=p();if(!e)throw Error(`An encryption key (NEXTBLOCK_ENCRYPTION_KEY or CORTEX_AI_ENCRYPTION_KEY) is required to manage stored secrets.`);return e}function g(e,t){return o({value:e,encryptionSecret:h(),now:t})}function _(e){return s({envelope:e,encryptionSecret:h()})}function v(e){if(!i(e))return null;for(let t of f())try{return s({envelope:e,encryptionSecret:t})}catch{}return null}exports.SECRET_ENVELOPE_ALGORITHM=t,exports.SECRET_ENVELOPE_VERSION=n,exports.decryptSecret=s,exports.decryptWithEnvKey=_,exports.encryptSecret=o,exports.encryptWithEnvKey=g,exports.getMaskedSecret=c,exports.getSecretEnvelopeStatus=l,exports.hasSecretEncryptionKey=m,exports.isEncryptedSecretEnvelope=i,exports.requireSecretEncryptionKey=h,exports.resolveSecretEncryptionKey=p,exports.tryDecryptWithEnvKey=v;
1
+ require("server-only");let e=require("node:crypto");var t=`aes-256-gcm`,n=1;function r(t){let n=t.trim();if(!n)throw Error(`A non-empty encryption secret is required to manage stored secrets.`);return(0,e.createHash)(`sha256`).update(n).digest()}function i(e){if(!e||typeof e!=`object`)return!1;let t=e;return t.algorithm===`aes-256-gcm`&&t.version===1&&typeof t.authTag==`string`&&typeof t.ciphertext==`string`&&typeof t.iv==`string`}function a(e){if(!i(e))throw Error(`Invalid encrypted secret payload.`);let t=e;return{algorithm:t.algorithm,authTag:t.authTag,ciphertext:t.ciphertext,iv:t.iv,last4:typeof t.last4==`string`?t.last4:``,updatedAt:typeof t.updatedAt==`string`?t.updatedAt:``,version:t.version}}function o(n){let i=n.value.trim();if(!i)throw Error(`A non-empty value is required to encrypt a secret.`);let a=r(n.encryptionSecret),o=(0,e.randomBytes)(12),s=(0,e.createCipheriv)(t,a,o),c=Buffer.concat([s.update(i,`utf8`),s.final()]);return{algorithm:t,authTag:s.getAuthTag().toString(`base64`),ciphertext:c.toString(`base64`),iv:o.toString(`base64`),last4:i.slice(-4),updatedAt:(n.now??new Date).toISOString(),version:1}}function s(n){let i=a(n.envelope),o=r(n.encryptionSecret);try{let n=(0,e.createDecipheriv)(t,o,Buffer.from(i.iv,`base64`));return n.setAuthTag(Buffer.from(i.authTag,`base64`)),Buffer.concat([n.update(Buffer.from(i.ciphertext,`base64`)),n.final()]).toString(`utf8`)}catch{throw Error(`Failed to decrypt stored secret.`)}}function c(e){let t=(e??``).trim();return t?`•••• ${t}`:`Stored secret`}function l(e){if(!i(e))return{hasStoredValue:!1,last4:null,maskedValue:null,updatedAt:null};let t=e,n=typeof t.last4==`string`&&t.last4?t.last4:null;return{hasStoredValue:!0,last4:n,maskedValue:c(n),updatedAt:typeof t.updatedAt==`string`&&t.updatedAt?t.updatedAt:null}}var u=`nextblock-secret-encryption-key-v1`;function d(){let t=process.env.SUPABASE_SERVICE_ROLE_KEY??process.env.SUPABASE_SECRET_KEY;return typeof t!=`string`||!t.trim()?null:(0,e.createHmac)(`sha256`,t.trim()).update(u).digest(`hex`)}function f(){let e=[],t=t=>{let n=typeof t==`string`?t.trim():``;n&&!e.includes(n)&&e.push(n)};return t(process.env.NEXTBLOCK_ENCRYPTION_KEY),t(process.env.CORTEX_AI_ENCRYPTION_KEY),t(d()),e}function p(){return f()[0]??null}function m(){return p()!==null}function h(){let e=p();if(!e)throw Error(`An encryption key (NEXTBLOCK_ENCRYPTION_KEY or CORTEX_AI_ENCRYPTION_KEY) is required to manage stored secrets.`);return e}function g(e,t){return o({value:e,encryptionSecret:h(),now:t})}function _(e){return s({envelope:e,encryptionSecret:h()})}function v(e){if(!i(e))return null;for(let t of f())try{return s({envelope:e,encryptionSecret:t})}catch{}return null}exports.SECRET_ENVELOPE_ALGORITHM=t,exports.SECRET_ENVELOPE_VERSION=n,exports.decryptSecret=s,exports.decryptWithEnvKey=_,exports.encryptSecret=o,exports.encryptWithEnvKey=g,exports.getMaskedSecret=c,exports.getSecretEnvelopeStatus=l,exports.hasSecretEncryptionKey=m,exports.isEncryptedSecretEnvelope=i,exports.requireSecretEncryptionKey=h,exports.resolveSecretEncryptionKey=p,exports.tryDecryptWithEnvKey=v;
@@ -1,3 +1,4 @@
1
+ import "server-only";
1
2
  import { createCipheriv as e, createDecipheriv as t, createHash as n, createHmac as r, randomBytes as i } from "node:crypto";
2
3
  //#region src/lib/secret-crypto.ts
3
4
  var a = "aes-256-gcm", o = 1;
@@ -1 +1 @@
1
- let e=require("@supabase/ssr"),t=require("@supabase/supabase-js"),n=require("next/headers");var r=`This module cannot be imported from a Client Component module. It should only be used from a Server Component.`;if(typeof window<`u`)throw Error(r);var i=()=>{let t=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL||`https://dummy.supabase.co`,r=process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY||process.env.SUPABASE_ANON_KEY||process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY||process.env.SUPABASE_PUBLISHABLE_KEY||`dummy-anon-key`;return(0,e.createServerClient)(t,r,{cookies:{getAll:async()=>{try{return(await(0,n.cookies)()).getAll()}catch{return[]}},setAll:async e=>{try{let t=await(0,n.cookies)();for(let{name:n,value:r,options:i}of e)r&&r.length>0?t.set({name:n,value:r,...i}):i&&Object.keys(i).length>0?t.delete({name:n,...i}):t.delete(n)}catch{}}}})};async function a(e){let{data:t,error:n}=await i().from(`profiles`).select(`id, full_name, avatar_url, role, updated_at, website`).eq(`id`,e).single();return n||!t?(console.error(`Error fetching profile (server-side):`,n?.message),null):t}async function o(){let{data:e,error:t}=await i().from(`languages`).select(`id, code, name, is_default, is_active, created_at, updated_at`).order(`name`,{ascending:!0});return t?(console.error(`Error fetching languages (server-side):`,t.message),[]):e||[]}var s=()=>{let e=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,n=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!e||!n)throw Error(`Missing Supabase Service Role environment variables`);return(0,t.createClient)(e,n,{auth:{autoRefreshToken:!1,persistSession:!1}})};exports.createClient=i,exports.getActiveLanguagesServerSide=o,exports.getProfileWithRoleServerSide=a,exports.getServiceRoleSupabaseClient=s;
1
+ let e=require("@supabase/ssr");require("server-only");let t=require("@supabase/supabase-js"),n=require("next/headers");var r=`This module cannot be imported from a Client Component module. It should only be used from a Server Component.`;if(typeof window<`u`)throw Error(r);var i=()=>{let t=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL||`https://dummy.supabase.co`,r=process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY||process.env.SUPABASE_ANON_KEY||process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY||process.env.SUPABASE_PUBLISHABLE_KEY||`dummy-anon-key`;return(0,e.createServerClient)(t,r,{cookies:{getAll:async()=>{try{return(await(0,n.cookies)()).getAll()}catch{return[]}},setAll:async e=>{try{let t=await(0,n.cookies)();for(let{name:n,value:r,options:i}of e)r&&r.length>0?t.set({name:n,value:r,...i}):i&&Object.keys(i).length>0?t.delete({name:n,...i}):t.delete(n)}catch{}}}})};async function a(e){let{data:t,error:n}=await i().from(`profiles`).select(`id, full_name, avatar_url, role, updated_at, website`).eq(`id`,e).single();return n||!t?(console.error(`Error fetching profile (server-side):`,n?.message),null):t}async function o(){let{data:e,error:t}=await i().from(`languages`).select(`id, code, name, is_default, is_active, created_at, updated_at`).order(`name`,{ascending:!0});return t?(console.error(`Error fetching languages (server-side):`,t.message),[]):e||[]}var s=()=>{let e=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,n=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!e||!n)throw Error(`Missing Supabase Service Role environment variables`);return(0,t.createClient)(e,n,{auth:{autoRefreshToken:!1,persistSession:!1}})};exports.createClient=i,exports.getActiveLanguagesServerSide=o,exports.getProfileWithRoleServerSide=a,exports.getServiceRoleSupabaseClient=s;
@@ -1,4 +1,5 @@
1
1
  import { createServerClient as e } from "@supabase/ssr";
2
+ import "server-only";
2
3
  import { createClient as t } from "@supabase/supabase-js";
3
4
  import { cookies as n } from "next/headers";
4
5
  //#region src/lib/supabase/server.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextblock-cms/db",
3
- "version": "0.22.1",
3
+ "version": "0.22.3",
4
4
  "license": "AGPL-3.0-or-later",
5
5
  "repository": {
6
6
  "type": "git",
package/server.cjs.js CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./lib/supabase/server.cjs.js"),t=require("./lib/supabase/ssg-client.cjs.js"),n=require("./lib/package-validation.cjs.js"),r=require("./lib/secret-crypto.cjs.js"),i=require("./lib/config-resolve.cjs.js");exports.PACKAGE_ACTIVATION_CACHE_TAG=n.PACKAGE_ACTIVATION_CACHE_TAG,exports.SECRET_ENVELOPE_ALGORITHM=r.SECRET_ENVELOPE_ALGORITHM,exports.SECRET_ENVELOPE_VERSION=r.SECRET_ENVELOPE_VERSION,exports.createClient=e.createClient,exports.decryptSecret=r.decryptSecret,exports.decryptWithEnvKey=r.decryptWithEnvKey,exports.encryptSecret=r.encryptSecret,exports.encryptWithEnvKey=r.encryptWithEnvKey,exports.getActiveLanguagesServerSide=e.getActiveLanguagesServerSide,exports.getMaskedSecret=r.getMaskedSecret,exports.getProfileWithRoleServerSide=e.getProfileWithRoleServerSide,exports.getSecretEnvelopeStatus=r.getSecretEnvelopeStatus,exports.getServiceRoleSupabaseClient=e.getServiceRoleSupabaseClient,exports.getSsgSupabaseClient=t.getSsgSupabaseClient,exports.hasSecretEncryptionKey=r.hasSecretEncryptionKey,exports.isEncryptedSecretEnvelope=r.isEncryptedSecretEnvelope,exports.isPackageActivationRowValid=n.isPackageActivationRowValid,exports.isSandboxEnvironment=i.isSandboxEnvironment,exports.requireSecretEncryptionKey=r.requireSecretEncryptionKey,exports.resolveConfigValue=i.resolveConfigValue,exports.resolvePackageActivationExpiry=n.resolvePackageActivationExpiry,exports.resolveSecretEncryptionKey=r.resolveSecretEncryptionKey,exports.tryDecryptWithEnvKey=r.tryDecryptWithEnvKey,exports.verifyPackageOnline=n.verifyPackageOnline;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./lib/supabase/server.cjs.js"),t=require("./lib/media-record.cjs.js"),n=require("./lib/supabase/ssg-client.cjs.js"),r=require("./lib/package-validation.cjs.js"),i=require("./lib/secret-crypto.cjs.js"),a=require("./lib/config-resolve.cjs.js");exports.PACKAGE_ACTIVATION_CACHE_TAG=r.PACKAGE_ACTIVATION_CACHE_TAG,exports.SECRET_ENVELOPE_ALGORITHM=i.SECRET_ENVELOPE_ALGORITHM,exports.SECRET_ENVELOPE_VERSION=i.SECRET_ENVELOPE_VERSION,exports.createClient=e.createClient,exports.decryptSecret=i.decryptSecret,exports.decryptWithEnvKey=i.decryptWithEnvKey,exports.encryptSecret=i.encryptSecret,exports.encryptWithEnvKey=i.encryptWithEnvKey,exports.getActiveLanguagesServerSide=e.getActiveLanguagesServerSide,exports.getMaskedSecret=i.getMaskedSecret,exports.getProfileWithRoleServerSide=e.getProfileWithRoleServerSide,exports.getSecretEnvelopeStatus=i.getSecretEnvelopeStatus,exports.getServiceRoleSupabaseClient=e.getServiceRoleSupabaseClient,exports.getSsgSupabaseClient=n.getSsgSupabaseClient,exports.hasSecretEncryptionKey=i.hasSecretEncryptionKey,exports.isEncryptedSecretEnvelope=i.isEncryptedSecretEnvelope,exports.isPackageActivationRowValid=r.isPackageActivationRowValid,exports.isSandboxEnvironment=a.isSandboxEnvironment,exports.recordMediaUploadAsActor=t.recordMediaUploadAsActor,exports.requireSecretEncryptionKey=i.requireSecretEncryptionKey,exports.resolveConfigValue=a.resolveConfigValue,exports.resolvePackageActivationExpiry=r.resolvePackageActivationExpiry,exports.resolveSecretEncryptionKey=i.resolveSecretEncryptionKey,exports.tryDecryptWithEnvKey=i.tryDecryptWithEnvKey,exports.verifyPackageOnline=r.verifyPackageOnline;
package/server.d.ts CHANGED
@@ -3,3 +3,4 @@ export { getSsgSupabaseClient } from './lib/supabase/ssg-client';
3
3
  export * from './lib/package-validation';
4
4
  export * from './lib/secret-crypto';
5
5
  export * from './lib/config-resolve';
6
+ export { recordMediaUploadAsActor, type ImageVariant, type MediaRecordResult, type MediaUploadPayload, } from './lib/media-record';
package/server.es.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createClient as e, getActiveLanguagesServerSide as t, getProfileWithRoleServerSide as n, getServiceRoleSupabaseClient as r } from "./lib/supabase/server.es.js";
2
- import { getSsgSupabaseClient as i } from "./lib/supabase/ssg-client.es.js";
3
- import { PACKAGE_ACTIVATION_CACHE_TAG as a, isPackageActivationRowValid as o, resolvePackageActivationExpiry as s, verifyPackageOnline as c } from "./lib/package-validation.es.js";
4
- import { SECRET_ENVELOPE_ALGORITHM as l, SECRET_ENVELOPE_VERSION as u, decryptSecret as d, decryptWithEnvKey as f, encryptSecret as p, encryptWithEnvKey as m, getMaskedSecret as h, getSecretEnvelopeStatus as g, hasSecretEncryptionKey as _, isEncryptedSecretEnvelope as v, requireSecretEncryptionKey as y, resolveSecretEncryptionKey as b, tryDecryptWithEnvKey as x } from "./lib/secret-crypto.es.js";
5
- import { isSandboxEnvironment as S, resolveConfigValue as C } from "./lib/config-resolve.es.js";
6
- export { a as PACKAGE_ACTIVATION_CACHE_TAG, l as SECRET_ENVELOPE_ALGORITHM, u as SECRET_ENVELOPE_VERSION, e as createClient, d as decryptSecret, f as decryptWithEnvKey, p as encryptSecret, m as encryptWithEnvKey, t as getActiveLanguagesServerSide, h as getMaskedSecret, n as getProfileWithRoleServerSide, g as getSecretEnvelopeStatus, r as getServiceRoleSupabaseClient, i as getSsgSupabaseClient, _ as hasSecretEncryptionKey, v as isEncryptedSecretEnvelope, o as isPackageActivationRowValid, S as isSandboxEnvironment, y as requireSecretEncryptionKey, C as resolveConfigValue, s as resolvePackageActivationExpiry, b as resolveSecretEncryptionKey, x as tryDecryptWithEnvKey, c as verifyPackageOnline };
2
+ import { recordMediaUploadAsActor as i } from "./lib/media-record.es.js";
3
+ import { getSsgSupabaseClient as a } from "./lib/supabase/ssg-client.es.js";
4
+ import { PACKAGE_ACTIVATION_CACHE_TAG as o, isPackageActivationRowValid as s, resolvePackageActivationExpiry as c, verifyPackageOnline as l } from "./lib/package-validation.es.js";
5
+ import { SECRET_ENVELOPE_ALGORITHM as u, SECRET_ENVELOPE_VERSION as d, decryptSecret as f, decryptWithEnvKey as p, encryptSecret as m, encryptWithEnvKey as h, getMaskedSecret as g, getSecretEnvelopeStatus as _, hasSecretEncryptionKey as v, isEncryptedSecretEnvelope as y, requireSecretEncryptionKey as b, resolveSecretEncryptionKey as x, tryDecryptWithEnvKey as S } from "./lib/secret-crypto.es.js";
6
+ import { isSandboxEnvironment as C, resolveConfigValue as w } from "./lib/config-resolve.es.js";
7
+ export { o as PACKAGE_ACTIVATION_CACHE_TAG, u as SECRET_ENVELOPE_ALGORITHM, d as SECRET_ENVELOPE_VERSION, e as createClient, f as decryptSecret, p as decryptWithEnvKey, m as encryptSecret, h as encryptWithEnvKey, t as getActiveLanguagesServerSide, g as getMaskedSecret, n as getProfileWithRoleServerSide, _ as getSecretEnvelopeStatus, r as getServiceRoleSupabaseClient, a as getSsgSupabaseClient, v as hasSecretEncryptionKey, y as isEncryptedSecretEnvelope, s as isPackageActivationRowValid, C as isSandboxEnvironment, i as recordMediaUploadAsActor, b as requireSecretEncryptionKey, w as resolveConfigValue, c as resolvePackageActivationExpiry, x as resolveSecretEncryptionKey, S as tryDecryptWithEnvKey, l as verifyPackageOnline };