@dalgoridim/headless-cms 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +10 -0
  2. package/README.md +178 -0
  3. package/dist/adapters/firestore/index.cjs +152 -0
  4. package/dist/adapters/firestore/index.cjs.map +1 -0
  5. package/dist/adapters/firestore/index.d.cts +39 -0
  6. package/dist/adapters/firestore/index.d.ts +39 -0
  7. package/dist/adapters/firestore/index.js +120 -0
  8. package/dist/adapters/firestore/index.js.map +1 -0
  9. package/dist/adapters/postgres/index.cjs +299 -0
  10. package/dist/adapters/postgres/index.cjs.map +1 -0
  11. package/dist/adapters/postgres/index.d.cts +59 -0
  12. package/dist/adapters/postgres/index.d.ts +59 -0
  13. package/dist/adapters/postgres/index.js +277 -0
  14. package/dist/adapters/postgres/index.js.map +1 -0
  15. package/dist/auth/firebase/client/index.cjs +153 -0
  16. package/dist/auth/firebase/client/index.cjs.map +1 -0
  17. package/dist/auth/firebase/client/index.d.cts +29 -0
  18. package/dist/auth/firebase/client/index.d.ts +29 -0
  19. package/dist/auth/firebase/client/index.js +138 -0
  20. package/dist/auth/firebase/client/index.js.map +1 -0
  21. package/dist/auth/firebase/index.cjs +81 -0
  22. package/dist/auth/firebase/index.cjs.map +1 -0
  23. package/dist/auth/firebase/index.d.cts +23 -0
  24. package/dist/auth/firebase/index.d.ts +23 -0
  25. package/dist/auth/firebase/index.js +46 -0
  26. package/dist/auth/firebase/index.js.map +1 -0
  27. package/dist/auth/nextauth/index.cjs +51 -0
  28. package/dist/auth/nextauth/index.cjs.map +1 -0
  29. package/dist/auth/nextauth/index.d.cts +30 -0
  30. package/dist/auth/nextauth/index.d.ts +30 -0
  31. package/dist/auth/nextauth/index.js +25 -0
  32. package/dist/auth/nextauth/index.js.map +1 -0
  33. package/dist/client/index.cjs +1018 -0
  34. package/dist/client/index.cjs.map +1 -0
  35. package/dist/client/index.d.cts +96 -0
  36. package/dist/client/index.d.ts +96 -0
  37. package/dist/client/index.js +994 -0
  38. package/dist/client/index.js.map +1 -0
  39. package/dist/index.cjs +19 -0
  40. package/dist/index.cjs.map +1 -0
  41. package/dist/index.d.cts +122 -0
  42. package/dist/index.d.ts +122 -0
  43. package/dist/index.js +1 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/server/index.cjs +128 -0
  46. package/dist/server/index.cjs.map +1 -0
  47. package/dist/server/index.d.cts +52 -0
  48. package/dist/server/index.d.ts +52 -0
  49. package/dist/server/index.js +99 -0
  50. package/dist/server/index.js.map +1 -0
  51. package/dist/storage/cloudinary/index.cjs +55 -0
  52. package/dist/storage/cloudinary/index.cjs.map +1 -0
  53. package/dist/storage/cloudinary/index.d.cts +17 -0
  54. package/dist/storage/cloudinary/index.d.ts +17 -0
  55. package/dist/storage/cloudinary/index.js +30 -0
  56. package/dist/storage/cloudinary/index.js.map +1 -0
  57. package/dist/storage/cloudinary/server.cjs +56 -0
  58. package/dist/storage/cloudinary/server.cjs.map +1 -0
  59. package/dist/storage/cloudinary/server.d.cts +16 -0
  60. package/dist/storage/cloudinary/server.d.ts +16 -0
  61. package/dist/storage/cloudinary/server.js +31 -0
  62. package/dist/storage/cloudinary/server.js.map +1 -0
  63. package/dist/storage/local/index.cjs +44 -0
  64. package/dist/storage/local/index.cjs.map +1 -0
  65. package/dist/storage/local/index.d.cts +15 -0
  66. package/dist/storage/local/index.d.ts +15 -0
  67. package/dist/storage/local/index.js +19 -0
  68. package/dist/storage/local/index.js.map +1 -0
  69. package/dist/storage/local/server.cjs +61 -0
  70. package/dist/storage/local/server.cjs.map +1 -0
  71. package/dist/storage/local/server.d.cts +16 -0
  72. package/dist/storage/local/server.d.ts +16 -0
  73. package/dist/storage/local/server.js +26 -0
  74. package/dist/storage/local/server.js.map +1 -0
  75. package/dist/storage/s3/index.cjs +52 -0
  76. package/dist/storage/s3/index.cjs.map +1 -0
  77. package/dist/storage/s3/index.d.cts +14 -0
  78. package/dist/storage/s3/index.d.ts +14 -0
  79. package/dist/storage/s3/index.js +27 -0
  80. package/dist/storage/s3/index.js.map +1 -0
  81. package/dist/storage/s3/server.cjs +61 -0
  82. package/dist/storage/s3/server.cjs.map +1 -0
  83. package/dist/storage/s3/server.d.cts +19 -0
  84. package/dist/storage/s3/server.d.ts +19 -0
  85. package/dist/storage/s3/server.js +36 -0
  86. package/dist/storage/s3/server.js.map +1 -0
  87. package/package.json +165 -0
@@ -0,0 +1,52 @@
1
+ import { DataAdapter, AuthAdapter, ServerStorageAdapter, AuthIdentity } from '../index.js';
2
+ export { ClientStorageAdapter, NestedSections, Query, Section, StorageAdapter } from '../index.js';
3
+
4
+ interface CmsHandlersDeps {
5
+ data: DataAdapter;
6
+ auth: AuthAdapter;
7
+ storage?: ServerStorageAdapter;
8
+ }
9
+ /** Next.js App Router passes dynamic params as a promise. */
10
+ type RouteContext = {
11
+ params: Promise<{
12
+ collection: string;
13
+ id: string;
14
+ }>;
15
+ };
16
+ type RouteHandler = (req: Request, ctx: RouteContext) => Promise<Response>;
17
+ type SignHandler = (req: Request) => Promise<Response>;
18
+ /**
19
+ * Builds the generic admin CRUD handlers, replacing a hand-written
20
+ * `/api/admin/[collection]/[id]/route.ts`. Mount like:
21
+ *
22
+ * ```ts
23
+ * // app/api/admin/[collection]/[id]/route.ts
24
+ * export const { GET, PATCH, PUT, DELETE } = createCmsHandlers({ data, auth });
25
+ * ```
26
+ *
27
+ * If a `storage` adapter with a `sign` method is provided, also mount its sign
28
+ * handler at e.g. `app/api/admin/sign/route.ts`:
29
+ *
30
+ * ```ts
31
+ * export const POST = createCmsHandlers({ data, auth, storage }).sign;
32
+ * ```
33
+ */
34
+ declare function createCmsHandlers(deps: CmsHandlersDeps): {
35
+ GET: RouteHandler;
36
+ PATCH: RouteHandler;
37
+ PUT: RouteHandler;
38
+ DELETE: RouteHandler;
39
+ sign: SignHandler;
40
+ };
41
+
42
+ /** Thrown when a request fails the admin gate; carried up to the route handler. */
43
+ declare class UnauthorizedError extends Error {
44
+ constructor(message?: string);
45
+ }
46
+ /**
47
+ * Wraps an {@link AuthAdapter} into a reusable server gate. Throws
48
+ * {@link UnauthorizedError} unless the request resolves to an admin identity.
49
+ */
50
+ declare function createAdminGate(auth: AuthAdapter): (req: Request) => Promise<AuthIdentity>;
51
+
52
+ export { AuthAdapter, AuthIdentity, type CmsHandlersDeps, DataAdapter, ServerStorageAdapter, UnauthorizedError, createAdminGate, createCmsHandlers };
@@ -0,0 +1,99 @@
1
+ // src/server/createAdminGate.ts
2
+ var UnauthorizedError = class extends Error {
3
+ constructor(message = "Unauthorized") {
4
+ super(message);
5
+ this.name = "UnauthorizedError";
6
+ }
7
+ };
8
+ function createAdminGate(auth) {
9
+ return async function requireAdmin(req) {
10
+ const identity = await auth.verifyRequest(req);
11
+ if (!identity || !identity.isAdmin) {
12
+ throw new UnauthorizedError(
13
+ identity ? "Forbidden - Not an authorized admin" : "Unauthorized"
14
+ );
15
+ }
16
+ return identity;
17
+ };
18
+ }
19
+
20
+ // src/server/createCmsHandlers.ts
21
+ function json(body, status = 200) {
22
+ return new Response(JSON.stringify(body), {
23
+ status,
24
+ headers: { "Content-Type": "application/json" }
25
+ });
26
+ }
27
+ function errorResponse(error) {
28
+ if (error instanceof UnauthorizedError && error.message === "Unauthorized") {
29
+ return json({ error: "Unauthorized", logout: true }, 401);
30
+ }
31
+ const message = error instanceof Error ? error.message : "Request failed";
32
+ return json({ error: message }, 403);
33
+ }
34
+ function createCmsHandlers(deps) {
35
+ const { data, auth, storage } = deps;
36
+ const requireAdmin = createAdminGate(auth);
37
+ const GET = async (req, ctx) => {
38
+ try {
39
+ await requireAdmin(req);
40
+ const { collection, id } = await ctx.params;
41
+ const doc = await data.fetchById(collection, id);
42
+ if (!doc) return json({ error: "Document not found" }, 404);
43
+ return json(doc);
44
+ } catch (error) {
45
+ return errorResponse(error);
46
+ }
47
+ };
48
+ const PATCH = async (req, ctx) => {
49
+ try {
50
+ await requireAdmin(req);
51
+ const { collection, id } = await ctx.params;
52
+ const body = await req.json();
53
+ await data.update(collection, id, body);
54
+ return json({ ok: true });
55
+ } catch (error) {
56
+ return errorResponse(error);
57
+ }
58
+ };
59
+ const PUT = async (req, ctx) => {
60
+ try {
61
+ await requireAdmin(req);
62
+ const { collection, id } = await ctx.params;
63
+ const body = await req.json();
64
+ await data.upsert(collection, id, body);
65
+ return json({ ok: true });
66
+ } catch (error) {
67
+ return errorResponse(error);
68
+ }
69
+ };
70
+ const DELETE = async (req, ctx) => {
71
+ try {
72
+ await requireAdmin(req);
73
+ const { collection, id } = await ctx.params;
74
+ await data.delete(collection, id);
75
+ return json({ ok: true });
76
+ } catch (error) {
77
+ return errorResponse(error);
78
+ }
79
+ };
80
+ const sign = async (req) => {
81
+ try {
82
+ await requireAdmin(req);
83
+ if (!(storage == null ? void 0 : storage.sign)) {
84
+ return json({ error: "No storage adapter with sign() configured" }, 404);
85
+ }
86
+ const result = await storage.sign(req);
87
+ return json(result);
88
+ } catch (error) {
89
+ return errorResponse(error);
90
+ }
91
+ };
92
+ return { GET, PATCH, PUT, DELETE, sign };
93
+ }
94
+ export {
95
+ UnauthorizedError,
96
+ createAdminGate,
97
+ createCmsHandlers
98
+ };
99
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server/createAdminGate.ts","../../src/server/createCmsHandlers.ts"],"sourcesContent":["import type { AuthAdapter, AuthIdentity } from \"../types\";\n\n/** Thrown when a request fails the admin gate; carried up to the route handler. */\nexport class UnauthorizedError extends Error {\n constructor(message = \"Unauthorized\") {\n super(message);\n this.name = \"UnauthorizedError\";\n }\n}\n\n/**\n * Wraps an {@link AuthAdapter} into a reusable server gate. Throws\n * {@link UnauthorizedError} unless the request resolves to an admin identity.\n */\nexport function createAdminGate(auth: AuthAdapter) {\n return async function requireAdmin(req: Request): Promise<AuthIdentity> {\n const identity = await auth.verifyRequest(req);\n if (!identity || !identity.isAdmin) {\n throw new UnauthorizedError(\n identity ? \"Forbidden - Not an authorized admin\" : \"Unauthorized\",\n );\n }\n return identity;\n };\n}\n","import type { DataAdapter, AuthAdapter, ServerStorageAdapter } from \"../types\";\nimport { createAdminGate, UnauthorizedError } from \"./createAdminGate\";\n\nexport interface CmsHandlersDeps {\n data: DataAdapter;\n auth: AuthAdapter;\n storage?: ServerStorageAdapter;\n}\n\n/** Next.js App Router passes dynamic params as a promise. */\ntype RouteContext = {\n params: Promise<{ collection: string; id: string }>;\n};\n\ntype RouteHandler = (req: Request, ctx: RouteContext) => Promise<Response>;\ntype SignHandler = (req: Request) => Promise<Response>;\n\nfunction json(body: unknown, status = 200): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\n/**\n * Translate any thrown error into a response. Auth failures return 401 with\n * `{ logout: true }` so a client interceptor can force sign-out.\n */\nfunction errorResponse(error: unknown): Response {\n if (error instanceof UnauthorizedError && error.message === \"Unauthorized\") {\n return json({ error: \"Unauthorized\", logout: true }, 401);\n }\n const message = error instanceof Error ? error.message : \"Request failed\";\n return json({ error: message }, 403);\n}\n\n/**\n * Builds the generic admin CRUD handlers, replacing a hand-written\n * `/api/admin/[collection]/[id]/route.ts`. Mount like:\n *\n * ```ts\n * // app/api/admin/[collection]/[id]/route.ts\n * export const { GET, PATCH, PUT, DELETE } = createCmsHandlers({ data, auth });\n * ```\n *\n * If a `storage` adapter with a `sign` method is provided, also mount its sign\n * handler at e.g. `app/api/admin/sign/route.ts`:\n *\n * ```ts\n * export const POST = createCmsHandlers({ data, auth, storage }).sign;\n * ```\n */\nexport function createCmsHandlers(deps: CmsHandlersDeps): {\n GET: RouteHandler;\n PATCH: RouteHandler;\n PUT: RouteHandler;\n DELETE: RouteHandler;\n sign: SignHandler;\n} {\n const { data, auth, storage } = deps;\n const requireAdmin = createAdminGate(auth);\n\n const GET: RouteHandler = async (req, ctx) => {\n try {\n await requireAdmin(req);\n const { collection, id } = await ctx.params;\n const doc = await data.fetchById(collection, id);\n if (!doc) return json({ error: \"Document not found\" }, 404);\n return json(doc);\n } catch (error) {\n return errorResponse(error);\n }\n };\n\n const PATCH: RouteHandler = async (req, ctx) => {\n try {\n await requireAdmin(req);\n const { collection, id } = await ctx.params;\n const body = await req.json();\n await data.update(collection, id, body);\n return json({ ok: true });\n } catch (error) {\n return errorResponse(error);\n }\n };\n\n const PUT: RouteHandler = async (req, ctx) => {\n try {\n await requireAdmin(req);\n const { collection, id } = await ctx.params;\n const body = await req.json();\n await data.upsert(collection, id, body);\n return json({ ok: true });\n } catch (error) {\n return errorResponse(error);\n }\n };\n\n const DELETE: RouteHandler = async (req, ctx) => {\n try {\n await requireAdmin(req);\n const { collection, id } = await ctx.params;\n await data.delete(collection, id);\n return json({ ok: true });\n } catch (error) {\n return errorResponse(error);\n }\n };\n\n const sign: SignHandler = async (req) => {\n try {\n await requireAdmin(req);\n if (!storage?.sign) {\n return json({ error: \"No storage adapter with sign() configured\" }, 404);\n }\n const result = await storage.sign(req);\n return json(result);\n } catch (error) {\n return errorResponse(error);\n }\n };\n\n return { GET, PATCH, PUT, DELETE, sign };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/storage/cloudinary/index.ts
21
+ var cloudinary_exports = {};
22
+ __export(cloudinary_exports, {
23
+ cloudinaryStorage: () => cloudinaryStorage
24
+ });
25
+ module.exports = __toCommonJS(cloudinary_exports);
26
+ function cloudinaryStorage(config = {}) {
27
+ var _a, _b;
28
+ const folder = (_a = config.folder) != null ? _a : "uploads";
29
+ const signEndpoint = (_b = config.signEndpoint) != null ? _b : "/api/admin/sign";
30
+ return {
31
+ async upload(file) {
32
+ const signRes = await fetch(signEndpoint, { method: "POST" });
33
+ if (!signRes.ok) throw new Error("Failed to get upload signature");
34
+ const { timestamp, signature, cloudName, apiKey } = await signRes.json();
35
+ const formData = new FormData();
36
+ formData.append("file", file);
37
+ formData.append("api_key", apiKey);
38
+ formData.append("timestamp", String(timestamp));
39
+ formData.append("signature", signature);
40
+ formData.append("folder", folder);
41
+ const uploadRes = await fetch(
42
+ `https://api.cloudinary.com/v1_1/${cloudName}/auto/upload`,
43
+ { method: "POST", body: formData }
44
+ );
45
+ if (!uploadRes.ok) throw new Error("Cloudinary upload failed");
46
+ const data = await uploadRes.json();
47
+ return { url: data.secure_url };
48
+ }
49
+ };
50
+ }
51
+ // Annotate the CommonJS export names for ESM import in node:
52
+ 0 && (module.exports = {
53
+ cloudinaryStorage
54
+ });
55
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/storage/cloudinary/index.ts"],"sourcesContent":["import type { ClientStorageAdapter } from \"../../types\";\n\nexport interface CloudinaryClientConfig {\n /** Upload folder. Must match the folder the server signs. Default `uploads`. */\n folder?: string;\n /** Endpoint that returns a signature. Default `/api/admin/sign`. */\n signEndpoint?: string;\n}\n\n/**\n * Cloudinary client storage: fetches a signature from the server, then posts the\n * file straight to Cloudinary. Pure `fetch` — no server dependencies, safe in\n * client components. The matching server signer lives at\n * `@dalgoridim/headless-cms/storage/cloudinary/server`.\n */\nexport function cloudinaryStorage(\n config: CloudinaryClientConfig = {},\n): ClientStorageAdapter {\n const folder = config.folder ?? \"uploads\";\n const signEndpoint = config.signEndpoint ?? \"/api/admin/sign\";\n\n return {\n async upload(file: File) {\n const signRes = await fetch(signEndpoint, { method: \"POST\" });\n if (!signRes.ok) throw new Error(\"Failed to get upload signature\");\n const { timestamp, signature, cloudName, apiKey } = await signRes.json();\n\n const formData = new FormData();\n formData.append(\"file\", file);\n formData.append(\"api_key\", apiKey);\n formData.append(\"timestamp\", String(timestamp));\n formData.append(\"signature\", signature);\n formData.append(\"folder\", folder);\n\n const uploadRes = await fetch(\n `https://api.cloudinary.com/v1_1/${cloudName}/auto/upload`,\n { method: \"POST\", body: formData },\n );\n if (!uploadRes.ok) throw new Error(\"Cloudinary upload failed\");\n const data = await uploadRes.json();\n return { url: data.secure_url as string };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAeO,SAAS,kBACd,SAAiC,CAAC,GACZ;AAjBxB;AAkBE,QAAM,UAAS,YAAO,WAAP,YAAiB;AAChC,QAAM,gBAAe,YAAO,iBAAP,YAAuB;AAE5C,SAAO;AAAA,IACL,MAAM,OAAO,MAAY;AACvB,YAAM,UAAU,MAAM,MAAM,cAAc,EAAE,QAAQ,OAAO,CAAC;AAC5D,UAAI,CAAC,QAAQ,GAAI,OAAM,IAAI,MAAM,gCAAgC;AACjE,YAAM,EAAE,WAAW,WAAW,WAAW,OAAO,IAAI,MAAM,QAAQ,KAAK;AAEvE,YAAM,WAAW,IAAI,SAAS;AAC9B,eAAS,OAAO,QAAQ,IAAI;AAC5B,eAAS,OAAO,WAAW,MAAM;AACjC,eAAS,OAAO,aAAa,OAAO,SAAS,CAAC;AAC9C,eAAS,OAAO,aAAa,SAAS;AACtC,eAAS,OAAO,UAAU,MAAM;AAEhC,YAAM,YAAY,MAAM;AAAA,QACtB,mCAAmC,SAAS;AAAA,QAC5C,EAAE,QAAQ,QAAQ,MAAM,SAAS;AAAA,MACnC;AACA,UAAI,CAAC,UAAU,GAAI,OAAM,IAAI,MAAM,0BAA0B;AAC7D,YAAM,OAAO,MAAM,UAAU,KAAK;AAClC,aAAO,EAAE,KAAK,KAAK,WAAqB;AAAA,IAC1C;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,17 @@
1
+ import { ClientStorageAdapter } from '../../index.cjs';
2
+
3
+ interface CloudinaryClientConfig {
4
+ /** Upload folder. Must match the folder the server signs. Default `uploads`. */
5
+ folder?: string;
6
+ /** Endpoint that returns a signature. Default `/api/admin/sign`. */
7
+ signEndpoint?: string;
8
+ }
9
+ /**
10
+ * Cloudinary client storage: fetches a signature from the server, then posts the
11
+ * file straight to Cloudinary. Pure `fetch` — no server dependencies, safe in
12
+ * client components. The matching server signer lives at
13
+ * `@dalgoridim/headless-cms/storage/cloudinary/server`.
14
+ */
15
+ declare function cloudinaryStorage(config?: CloudinaryClientConfig): ClientStorageAdapter;
16
+
17
+ export { type CloudinaryClientConfig, cloudinaryStorage };
@@ -0,0 +1,17 @@
1
+ import { ClientStorageAdapter } from '../../index.js';
2
+
3
+ interface CloudinaryClientConfig {
4
+ /** Upload folder. Must match the folder the server signs. Default `uploads`. */
5
+ folder?: string;
6
+ /** Endpoint that returns a signature. Default `/api/admin/sign`. */
7
+ signEndpoint?: string;
8
+ }
9
+ /**
10
+ * Cloudinary client storage: fetches a signature from the server, then posts the
11
+ * file straight to Cloudinary. Pure `fetch` — no server dependencies, safe in
12
+ * client components. The matching server signer lives at
13
+ * `@dalgoridim/headless-cms/storage/cloudinary/server`.
14
+ */
15
+ declare function cloudinaryStorage(config?: CloudinaryClientConfig): ClientStorageAdapter;
16
+
17
+ export { type CloudinaryClientConfig, cloudinaryStorage };
@@ -0,0 +1,30 @@
1
+ // src/storage/cloudinary/index.ts
2
+ function cloudinaryStorage(config = {}) {
3
+ var _a, _b;
4
+ const folder = (_a = config.folder) != null ? _a : "uploads";
5
+ const signEndpoint = (_b = config.signEndpoint) != null ? _b : "/api/admin/sign";
6
+ return {
7
+ async upload(file) {
8
+ const signRes = await fetch(signEndpoint, { method: "POST" });
9
+ if (!signRes.ok) throw new Error("Failed to get upload signature");
10
+ const { timestamp, signature, cloudName, apiKey } = await signRes.json();
11
+ const formData = new FormData();
12
+ formData.append("file", file);
13
+ formData.append("api_key", apiKey);
14
+ formData.append("timestamp", String(timestamp));
15
+ formData.append("signature", signature);
16
+ formData.append("folder", folder);
17
+ const uploadRes = await fetch(
18
+ `https://api.cloudinary.com/v1_1/${cloudName}/auto/upload`,
19
+ { method: "POST", body: formData }
20
+ );
21
+ if (!uploadRes.ok) throw new Error("Cloudinary upload failed");
22
+ const data = await uploadRes.json();
23
+ return { url: data.secure_url };
24
+ }
25
+ };
26
+ }
27
+ export {
28
+ cloudinaryStorage
29
+ };
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/storage/cloudinary/index.ts"],"sourcesContent":["import type { ClientStorageAdapter } from \"../../types\";\n\nexport interface CloudinaryClientConfig {\n /** Upload folder. Must match the folder the server signs. Default `uploads`. */\n folder?: string;\n /** Endpoint that returns a signature. Default `/api/admin/sign`. */\n signEndpoint?: string;\n}\n\n/**\n * Cloudinary client storage: fetches a signature from the server, then posts the\n * file straight to Cloudinary. Pure `fetch` — no server dependencies, safe in\n * client components. The matching server signer lives at\n * `@dalgoridim/headless-cms/storage/cloudinary/server`.\n */\nexport function cloudinaryStorage(\n config: CloudinaryClientConfig = {},\n): ClientStorageAdapter {\n const folder = config.folder ?? \"uploads\";\n const signEndpoint = config.signEndpoint ?? \"/api/admin/sign\";\n\n return {\n async upload(file: File) {\n const signRes = await fetch(signEndpoint, { method: \"POST\" });\n if (!signRes.ok) throw new Error(\"Failed to get upload signature\");\n const { timestamp, signature, cloudName, apiKey } = await signRes.json();\n\n const formData = new FormData();\n formData.append(\"file\", file);\n formData.append(\"api_key\", apiKey);\n formData.append(\"timestamp\", String(timestamp));\n formData.append(\"signature\", signature);\n formData.append(\"folder\", folder);\n\n const uploadRes = await fetch(\n `https://api.cloudinary.com/v1_1/${cloudName}/auto/upload`,\n { method: \"POST\", body: formData },\n );\n if (!uploadRes.ok) throw new Error(\"Cloudinary upload failed\");\n const data = await uploadRes.json();\n return { url: data.secure_url as string };\n },\n };\n}\n"],"mappings":";AAeO,SAAS,kBACd,SAAiC,CAAC,GACZ;AAjBxB;AAkBE,QAAM,UAAS,YAAO,WAAP,YAAiB;AAChC,QAAM,gBAAe,YAAO,iBAAP,YAAuB;AAE5C,SAAO;AAAA,IACL,MAAM,OAAO,MAAY;AACvB,YAAM,UAAU,MAAM,MAAM,cAAc,EAAE,QAAQ,OAAO,CAAC;AAC5D,UAAI,CAAC,QAAQ,GAAI,OAAM,IAAI,MAAM,gCAAgC;AACjE,YAAM,EAAE,WAAW,WAAW,WAAW,OAAO,IAAI,MAAM,QAAQ,KAAK;AAEvE,YAAM,WAAW,IAAI,SAAS;AAC9B,eAAS,OAAO,QAAQ,IAAI;AAC5B,eAAS,OAAO,WAAW,MAAM;AACjC,eAAS,OAAO,aAAa,OAAO,SAAS,CAAC;AAC9C,eAAS,OAAO,aAAa,SAAS;AACtC,eAAS,OAAO,UAAU,MAAM;AAEhC,YAAM,YAAY,MAAM;AAAA,QACtB,mCAAmC,SAAS;AAAA,QAC5C,EAAE,QAAQ,QAAQ,MAAM,SAAS;AAAA,MACnC;AACA,UAAI,CAAC,UAAU,GAAI,OAAM,IAAI,MAAM,0BAA0B;AAC7D,YAAM,OAAO,MAAM,UAAU,KAAK;AAClC,aAAO,EAAE,KAAK,KAAK,WAAqB;AAAA,IAC1C;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/storage/cloudinary/server.ts
21
+ var server_exports = {};
22
+ __export(server_exports, {
23
+ cloudinarySign: () => cloudinarySign
24
+ });
25
+ module.exports = __toCommonJS(server_exports);
26
+ var import_cloudinary = require("cloudinary");
27
+ function cloudinarySign(config = {}) {
28
+ var _a;
29
+ const folder = (_a = config.folder) != null ? _a : "uploads";
30
+ return {
31
+ async sign() {
32
+ import_cloudinary.v2.config({
33
+ cloud_name: config.cloudName,
34
+ api_key: config.apiKey,
35
+ api_secret: config.apiSecret
36
+ });
37
+ const timestamp = Math.floor(Date.now() / 1e3);
38
+ const signature = import_cloudinary.v2.utils.api_sign_request(
39
+ { timestamp, folder },
40
+ config.apiSecret
41
+ );
42
+ return {
43
+ timestamp,
44
+ signature,
45
+ folder,
46
+ cloudName: config.cloudName,
47
+ apiKey: config.apiKey
48
+ };
49
+ }
50
+ };
51
+ }
52
+ // Annotate the CommonJS export names for ESM import in node:
53
+ 0 && (module.exports = {
54
+ cloudinarySign
55
+ });
56
+ //# sourceMappingURL=server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/storage/cloudinary/server.ts"],"sourcesContent":["import { v2 as cloudinary } from \"cloudinary\";\nimport type { ServerStorageAdapter } from \"../../types\";\n\nexport interface CloudinaryServerConfig {\n cloudName?: string;\n apiKey?: string;\n apiSecret?: string;\n /** Upload folder. Must match the client's folder. Default `uploads`. */\n folder?: string;\n}\n\n/**\n * Cloudinary server signer. Mount its `sign` via `createCmsHandlers`. Imports the\n * Cloudinary SDK statically, so only ever import this from server code.\n */\nexport function cloudinarySign(\n config: CloudinaryServerConfig = {},\n): ServerStorageAdapter {\n const folder = config.folder ?? \"uploads\";\n\n return {\n async sign() {\n cloudinary.config({\n cloud_name: config.cloudName,\n api_key: config.apiKey,\n api_secret: config.apiSecret,\n });\n const timestamp = Math.floor(Date.now() / 1000);\n const signature = cloudinary.utils.api_sign_request(\n { timestamp, folder },\n config.apiSecret!,\n );\n return {\n timestamp,\n signature,\n folder,\n cloudName: config.cloudName,\n apiKey: config.apiKey,\n };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAiC;AAe1B,SAAS,eACd,SAAiC,CAAC,GACZ;AAjBxB;AAkBE,QAAM,UAAS,YAAO,WAAP,YAAiB;AAEhC,SAAO;AAAA,IACL,MAAM,OAAO;AACX,wBAAAA,GAAW,OAAO;AAAA,QAChB,YAAY,OAAO;AAAA,QACnB,SAAS,OAAO;AAAA,QAChB,YAAY,OAAO;AAAA,MACrB,CAAC;AACD,YAAM,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC9C,YAAM,YAAY,kBAAAA,GAAW,MAAM;AAAA,QACjC,EAAE,WAAW,OAAO;AAAA,QACpB,OAAO;AAAA,MACT;AACA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW,OAAO;AAAA,QAClB,QAAQ,OAAO;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AACF;","names":["cloudinary"]}
@@ -0,0 +1,16 @@
1
+ import { ServerStorageAdapter } from '../../index.cjs';
2
+
3
+ interface CloudinaryServerConfig {
4
+ cloudName?: string;
5
+ apiKey?: string;
6
+ apiSecret?: string;
7
+ /** Upload folder. Must match the client's folder. Default `uploads`. */
8
+ folder?: string;
9
+ }
10
+ /**
11
+ * Cloudinary server signer. Mount its `sign` via `createCmsHandlers`. Imports the
12
+ * Cloudinary SDK statically, so only ever import this from server code.
13
+ */
14
+ declare function cloudinarySign(config?: CloudinaryServerConfig): ServerStorageAdapter;
15
+
16
+ export { type CloudinaryServerConfig, cloudinarySign };
@@ -0,0 +1,16 @@
1
+ import { ServerStorageAdapter } from '../../index.js';
2
+
3
+ interface CloudinaryServerConfig {
4
+ cloudName?: string;
5
+ apiKey?: string;
6
+ apiSecret?: string;
7
+ /** Upload folder. Must match the client's folder. Default `uploads`. */
8
+ folder?: string;
9
+ }
10
+ /**
11
+ * Cloudinary server signer. Mount its `sign` via `createCmsHandlers`. Imports the
12
+ * Cloudinary SDK statically, so only ever import this from server code.
13
+ */
14
+ declare function cloudinarySign(config?: CloudinaryServerConfig): ServerStorageAdapter;
15
+
16
+ export { type CloudinaryServerConfig, cloudinarySign };
@@ -0,0 +1,31 @@
1
+ // src/storage/cloudinary/server.ts
2
+ import { v2 as cloudinary } from "cloudinary";
3
+ function cloudinarySign(config = {}) {
4
+ var _a;
5
+ const folder = (_a = config.folder) != null ? _a : "uploads";
6
+ return {
7
+ async sign() {
8
+ cloudinary.config({
9
+ cloud_name: config.cloudName,
10
+ api_key: config.apiKey,
11
+ api_secret: config.apiSecret
12
+ });
13
+ const timestamp = Math.floor(Date.now() / 1e3);
14
+ const signature = cloudinary.utils.api_sign_request(
15
+ { timestamp, folder },
16
+ config.apiSecret
17
+ );
18
+ return {
19
+ timestamp,
20
+ signature,
21
+ folder,
22
+ cloudName: config.cloudName,
23
+ apiKey: config.apiKey
24
+ };
25
+ }
26
+ };
27
+ }
28
+ export {
29
+ cloudinarySign
30
+ };
31
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/storage/cloudinary/server.ts"],"sourcesContent":["import { v2 as cloudinary } from \"cloudinary\";\nimport type { ServerStorageAdapter } from \"../../types\";\n\nexport interface CloudinaryServerConfig {\n cloudName?: string;\n apiKey?: string;\n apiSecret?: string;\n /** Upload folder. Must match the client's folder. Default `uploads`. */\n folder?: string;\n}\n\n/**\n * Cloudinary server signer. Mount its `sign` via `createCmsHandlers`. Imports the\n * Cloudinary SDK statically, so only ever import this from server code.\n */\nexport function cloudinarySign(\n config: CloudinaryServerConfig = {},\n): ServerStorageAdapter {\n const folder = config.folder ?? \"uploads\";\n\n return {\n async sign() {\n cloudinary.config({\n cloud_name: config.cloudName,\n api_key: config.apiKey,\n api_secret: config.apiSecret,\n });\n const timestamp = Math.floor(Date.now() / 1000);\n const signature = cloudinary.utils.api_sign_request(\n { timestamp, folder },\n config.apiSecret!,\n );\n return {\n timestamp,\n signature,\n folder,\n cloudName: config.cloudName,\n apiKey: config.apiKey,\n };\n },\n };\n}\n"],"mappings":";AAAA,SAAS,MAAM,kBAAkB;AAe1B,SAAS,eACd,SAAiC,CAAC,GACZ;AAjBxB;AAkBE,QAAM,UAAS,YAAO,WAAP,YAAiB;AAEhC,SAAO;AAAA,IACL,MAAM,OAAO;AACX,iBAAW,OAAO;AAAA,QAChB,YAAY,OAAO;AAAA,QACnB,SAAS,OAAO;AAAA,QAChB,YAAY,OAAO;AAAA,MACrB,CAAC;AACD,YAAM,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC9C,YAAM,YAAY,WAAW,MAAM;AAAA,QACjC,EAAE,WAAW,OAAO;AAAA,QACpB,OAAO;AAAA,MACT;AACA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW,OAAO;AAAA,QAClB,QAAQ,OAAO;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/storage/local/index.ts
21
+ var local_exports = {};
22
+ __export(local_exports, {
23
+ localStorage: () => localStorage
24
+ });
25
+ module.exports = __toCommonJS(local_exports);
26
+ function localStorage(config = {}) {
27
+ var _a;
28
+ const signEndpoint = (_a = config.signEndpoint) != null ? _a : "/api/admin/sign";
29
+ return {
30
+ async upload(file) {
31
+ const formData = new FormData();
32
+ formData.append("file", file);
33
+ const res = await fetch(signEndpoint, { method: "POST", body: formData });
34
+ if (!res.ok) throw new Error("Local upload failed");
35
+ const { url } = await res.json();
36
+ return { url };
37
+ }
38
+ };
39
+ }
40
+ // Annotate the CommonJS export names for ESM import in node:
41
+ 0 && (module.exports = {
42
+ localStorage
43
+ });
44
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/storage/local/index.ts"],"sourcesContent":["import type { ClientStorageAdapter } from \"../../types\";\n\nexport interface LocalClientConfig {\n /** Endpoint that accepts the upload. Default `/api/admin/sign`. */\n signEndpoint?: string;\n}\n\n/**\n * Local-filesystem client storage: posts the file to the server, which writes it\n * to disk and returns the public URL. Pure `fetch` — safe in client components.\n * The matching server handler lives at\n * `@dalgoridim/headless-cms/storage/local/server`.\n */\nexport function localStorage(\n config: LocalClientConfig = {},\n): ClientStorageAdapter {\n const signEndpoint = config.signEndpoint ?? \"/api/admin/sign\";\n\n return {\n async upload(file: File) {\n const formData = new FormData();\n formData.append(\"file\", file);\n const res = await fetch(signEndpoint, { method: \"POST\", body: formData });\n if (!res.ok) throw new Error(\"Local upload failed\");\n const { url } = await res.json();\n return { url: url as string };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAaO,SAAS,aACd,SAA4B,CAAC,GACP;AAfxB;AAgBE,QAAM,gBAAe,YAAO,iBAAP,YAAuB;AAE5C,SAAO;AAAA,IACL,MAAM,OAAO,MAAY;AACvB,YAAM,WAAW,IAAI,SAAS;AAC9B,eAAS,OAAO,QAAQ,IAAI;AAC5B,YAAM,MAAM,MAAM,MAAM,cAAc,EAAE,QAAQ,QAAQ,MAAM,SAAS,CAAC;AACxE,UAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,qBAAqB;AAClD,YAAM,EAAE,IAAI,IAAI,MAAM,IAAI,KAAK;AAC/B,aAAO,EAAE,IAAmB;AAAA,IAC9B;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,15 @@
1
+ import { ClientStorageAdapter } from '../../index.cjs';
2
+
3
+ interface LocalClientConfig {
4
+ /** Endpoint that accepts the upload. Default `/api/admin/sign`. */
5
+ signEndpoint?: string;
6
+ }
7
+ /**
8
+ * Local-filesystem client storage: posts the file to the server, which writes it
9
+ * to disk and returns the public URL. Pure `fetch` — safe in client components.
10
+ * The matching server handler lives at
11
+ * `@dalgoridim/headless-cms/storage/local/server`.
12
+ */
13
+ declare function localStorage(config?: LocalClientConfig): ClientStorageAdapter;
14
+
15
+ export { type LocalClientConfig, localStorage };
@@ -0,0 +1,15 @@
1
+ import { ClientStorageAdapter } from '../../index.js';
2
+
3
+ interface LocalClientConfig {
4
+ /** Endpoint that accepts the upload. Default `/api/admin/sign`. */
5
+ signEndpoint?: string;
6
+ }
7
+ /**
8
+ * Local-filesystem client storage: posts the file to the server, which writes it
9
+ * to disk and returns the public URL. Pure `fetch` — safe in client components.
10
+ * The matching server handler lives at
11
+ * `@dalgoridim/headless-cms/storage/local/server`.
12
+ */
13
+ declare function localStorage(config?: LocalClientConfig): ClientStorageAdapter;
14
+
15
+ export { type LocalClientConfig, localStorage };
@@ -0,0 +1,19 @@
1
+ // src/storage/local/index.ts
2
+ function localStorage(config = {}) {
3
+ var _a;
4
+ const signEndpoint = (_a = config.signEndpoint) != null ? _a : "/api/admin/sign";
5
+ return {
6
+ async upload(file) {
7
+ const formData = new FormData();
8
+ formData.append("file", file);
9
+ const res = await fetch(signEndpoint, { method: "POST", body: formData });
10
+ if (!res.ok) throw new Error("Local upload failed");
11
+ const { url } = await res.json();
12
+ return { url };
13
+ }
14
+ };
15
+ }
16
+ export {
17
+ localStorage
18
+ };
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/storage/local/index.ts"],"sourcesContent":["import type { ClientStorageAdapter } from \"../../types\";\n\nexport interface LocalClientConfig {\n /** Endpoint that accepts the upload. Default `/api/admin/sign`. */\n signEndpoint?: string;\n}\n\n/**\n * Local-filesystem client storage: posts the file to the server, which writes it\n * to disk and returns the public URL. Pure `fetch` — safe in client components.\n * The matching server handler lives at\n * `@dalgoridim/headless-cms/storage/local/server`.\n */\nexport function localStorage(\n config: LocalClientConfig = {},\n): ClientStorageAdapter {\n const signEndpoint = config.signEndpoint ?? \"/api/admin/sign\";\n\n return {\n async upload(file: File) {\n const formData = new FormData();\n formData.append(\"file\", file);\n const res = await fetch(signEndpoint, { method: \"POST\", body: formData });\n if (!res.ok) throw new Error(\"Local upload failed\");\n const { url } = await res.json();\n return { url: url as string };\n },\n };\n}\n"],"mappings":";AAaO,SAAS,aACd,SAA4B,CAAC,GACP;AAfxB;AAgBE,QAAM,gBAAe,YAAO,iBAAP,YAAuB;AAE5C,SAAO;AAAA,IACL,MAAM,OAAO,MAAY;AACvB,YAAM,WAAW,IAAI,SAAS;AAC9B,eAAS,OAAO,QAAQ,IAAI;AAC5B,YAAM,MAAM,MAAM,MAAM,cAAc,EAAE,QAAQ,QAAQ,MAAM,SAAS,CAAC;AACxE,UAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,qBAAqB;AAClD,YAAM,EAAE,IAAI,IAAI,MAAM,IAAI,KAAK;AAC/B,aAAO,EAAE,IAAmB;AAAA,IAC9B;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/storage/local/server.ts
31
+ var server_exports = {};
32
+ __export(server_exports, {
33
+ localSign: () => localSign
34
+ });
35
+ module.exports = __toCommonJS(server_exports);
36
+ var import_promises = require("fs/promises");
37
+ var import_node_path = __toESM(require("path"), 1);
38
+ function localSign(config = {}) {
39
+ var _a, _b;
40
+ const uploadDir = (_a = config.uploadDir) != null ? _a : "public/uploads";
41
+ const publicPath = ((_b = config.publicPath) != null ? _b : "/uploads").replace(/\/$/, "");
42
+ return {
43
+ async sign(req) {
44
+ const form = await req.formData();
45
+ const file = form.get("file");
46
+ if (!(file instanceof File)) throw new Error("No file provided");
47
+ const safeName = file.name.replace(/[^a-zA-Z0-9._-]/g, "_");
48
+ const fileName = `${Date.now()}-${safeName}`;
49
+ const absDir = import_node_path.default.resolve(process.cwd(), uploadDir);
50
+ await (0, import_promises.mkdir)(absDir, { recursive: true });
51
+ const buffer = Buffer.from(await file.arrayBuffer());
52
+ await (0, import_promises.writeFile)(import_node_path.default.join(absDir, fileName), buffer);
53
+ return { url: `${publicPath}/${fileName}` };
54
+ }
55
+ };
56
+ }
57
+ // Annotate the CommonJS export names for ESM import in node:
58
+ 0 && (module.exports = {
59
+ localSign
60
+ });
61
+ //# sourceMappingURL=server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/storage/local/server.ts"],"sourcesContent":["import { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { ServerStorageAdapter } from \"../../types\";\n\nexport interface LocalServerConfig {\n /** Directory to write uploads into. Default `public/uploads`. */\n uploadDir?: string;\n /** Public URL path the directory is served from. Default `/uploads`. */\n publicPath?: string;\n}\n\n/**\n * Local-filesystem server handler: receives the multipart file, writes it to\n * disk, and returns its public URL. Mount its `sign` via `createCmsHandlers`.\n * Server-only (uses Node `fs`).\n */\nexport function localSign(config: LocalServerConfig = {}): ServerStorageAdapter {\n const uploadDir = config.uploadDir ?? \"public/uploads\";\n const publicPath = (config.publicPath ?? \"/uploads\").replace(/\\/$/, \"\");\n\n return {\n async sign(req: Request) {\n const form = await req.formData();\n const file = form.get(\"file\");\n if (!(file instanceof File)) throw new Error(\"No file provided\");\n\n const safeName = file.name.replace(/[^a-zA-Z0-9._-]/g, \"_\");\n const fileName = `${Date.now()}-${safeName}`;\n const absDir = path.resolve(process.cwd(), uploadDir);\n await mkdir(absDir, { recursive: true });\n\n const buffer = Buffer.from(await file.arrayBuffer());\n await writeFile(path.join(absDir, fileName), buffer);\n\n return { url: `${publicPath}/${fileName}` };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAiC;AACjC,uBAAiB;AAeV,SAAS,UAAU,SAA4B,CAAC,GAAyB;AAhBhF;AAiBE,QAAM,aAAY,YAAO,cAAP,YAAoB;AACtC,QAAM,eAAc,YAAO,eAAP,YAAqB,YAAY,QAAQ,OAAO,EAAE;AAEtE,SAAO;AAAA,IACL,MAAM,KAAK,KAAc;AACvB,YAAM,OAAO,MAAM,IAAI,SAAS;AAChC,YAAM,OAAO,KAAK,IAAI,MAAM;AAC5B,UAAI,EAAE,gBAAgB,MAAO,OAAM,IAAI,MAAM,kBAAkB;AAE/D,YAAM,WAAW,KAAK,KAAK,QAAQ,oBAAoB,GAAG;AAC1D,YAAM,WAAW,GAAG,KAAK,IAAI,CAAC,IAAI,QAAQ;AAC1C,YAAM,SAAS,iBAAAA,QAAK,QAAQ,QAAQ,IAAI,GAAG,SAAS;AACpD,gBAAM,uBAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AAEvC,YAAM,SAAS,OAAO,KAAK,MAAM,KAAK,YAAY,CAAC;AACnD,gBAAM,2BAAU,iBAAAA,QAAK,KAAK,QAAQ,QAAQ,GAAG,MAAM;AAEnD,aAAO,EAAE,KAAK,GAAG,UAAU,IAAI,QAAQ,GAAG;AAAA,IAC5C;AAAA,EACF;AACF;","names":["path"]}
@@ -0,0 +1,16 @@
1
+ import { ServerStorageAdapter } from '../../index.cjs';
2
+
3
+ interface LocalServerConfig {
4
+ /** Directory to write uploads into. Default `public/uploads`. */
5
+ uploadDir?: string;
6
+ /** Public URL path the directory is served from. Default `/uploads`. */
7
+ publicPath?: string;
8
+ }
9
+ /**
10
+ * Local-filesystem server handler: receives the multipart file, writes it to
11
+ * disk, and returns its public URL. Mount its `sign` via `createCmsHandlers`.
12
+ * Server-only (uses Node `fs`).
13
+ */
14
+ declare function localSign(config?: LocalServerConfig): ServerStorageAdapter;
15
+
16
+ export { type LocalServerConfig, localSign };