autoblogger 0.2.18 → 0.2.19

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/dist/index.d.mts CHANGED
@@ -743,6 +743,61 @@ declare function formatDate(date: Date | string, options?: Intl.DateTimeFormatOp
743
743
  */
744
744
  declare function truncate(text: string, maxLength: number): string;
745
745
 
746
+ /**
747
+ * Built-in storage module for autoblogger.
748
+ * Auto-detects cloud storage (S3-compatible) or falls back to local filesystem.
749
+ *
750
+ * Supported providers:
751
+ * - DigitalOcean Spaces (set SPACES_KEY, SPACES_SECRET)
752
+ * - AWS S3 (set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_S3_BUCKET)
753
+ * - Local filesystem (no config needed, saves to public/uploads)
754
+ */
755
+ interface UploadResult {
756
+ url: string;
757
+ key: string;
758
+ }
759
+ interface StorageConfig {
760
+ s3?: {
761
+ accessKeyId: string;
762
+ secretAccessKey: string;
763
+ bucket: string;
764
+ region?: string;
765
+ endpoint?: string;
766
+ cdnEndpoint?: string;
767
+ };
768
+ local?: {
769
+ uploadDir?: string;
770
+ urlPrefix?: string;
771
+ };
772
+ }
773
+ /**
774
+ * Detect storage configuration from environment variables
775
+ */
776
+ declare function detectStorageConfig(): StorageConfig;
777
+ /**
778
+ * Upload a file using auto-detected or provided storage config
779
+ */
780
+ declare function uploadFile(buffer: Buffer, filename: string, contentType: string, config?: StorageConfig): Promise<UploadResult>;
781
+ /**
782
+ * Create a storage upload handler for autoblogger config.
783
+ * Auto-detects cloud storage from env vars, falls back to local.
784
+ *
785
+ * Usage:
786
+ * ```ts
787
+ * import { createStorageHandler } from 'autoblogger'
788
+ *
789
+ * const cms = createAutoblogger({
790
+ * // ... other config
791
+ * storage: {
792
+ * upload: createStorageHandler()
793
+ * }
794
+ * })
795
+ * ```
796
+ */
797
+ declare function createStorageHandler(config?: StorageConfig): (file: File) => Promise<{
798
+ url: string;
799
+ }>;
800
+
746
801
  /**
747
802
  * Comment types and client-side API helpers for the editor commenting system.
748
803
  * Used for collaborative inline comments on posts.
@@ -819,4 +874,4 @@ declare function applyCommentMarks(editor: Editor, comments: CommentWithUser[]):
819
874
  */
820
875
  declare function scrollToComment(editor: Editor, commentId: string): void;
821
876
 
822
- export { type AIModel, AI_MODELS, type AutoDraftConfig, type AutobloggerServer as Autoblogger, type AutobloggerServerConfig as AutobloggerConfig, type BaseCrud, CommentMark, type CommentWithUser, type CreateCommentData, type CrudOptions, type CustomFieldConfig, type CustomFieldProps, DEFAULT_AUTO_DRAFT_TEMPLATE, DEFAULT_CHAT_TEMPLATE, DEFAULT_EXPAND_PLAN_TEMPLATE, DEFAULT_GENERATE_TEMPLATE, DEFAULT_PLAN_RULES, DEFAULT_PLAN_TEMPLATE, DEFAULT_REWRITE_TEMPLATE, type Destination, type DestinationDispatcher, type DestinationEvent, type DestinationResult, type DestinationsConfig, type DispatchResult, type DispatcherConfig, type GenerationResult, Post, type RssArticle, type SelectionState, type Session, type StylesConfig, addCommentMark, applyCommentMarks, buildAutoDraftPrompt, buildChatPrompt, buildExpandPlanPrompt, buildGeneratePrompt, buildPlanPrompt, buildRewritePrompt, canDeleteComment, canEditComment, createAPIHandler, createAutoblogger, createCommentsClient, createCrudData, createDestinationDispatcher, fetchRssFeeds, filterByKeywords, formatDate, generate, getDefaultModel, getModel, parseGeneratedContent, removeCommentMark, resolveModel, runAutoDraft, scrollToComment, truncate, validateSchema };
877
+ export { type AIModel, AI_MODELS, type AutoDraftConfig, type AutobloggerServer as Autoblogger, type AutobloggerServerConfig as AutobloggerConfig, type BaseCrud, CommentMark, type CommentWithUser, type CreateCommentData, type CrudOptions, type CustomFieldConfig, type CustomFieldProps, DEFAULT_AUTO_DRAFT_TEMPLATE, DEFAULT_CHAT_TEMPLATE, DEFAULT_EXPAND_PLAN_TEMPLATE, DEFAULT_GENERATE_TEMPLATE, DEFAULT_PLAN_RULES, DEFAULT_PLAN_TEMPLATE, DEFAULT_REWRITE_TEMPLATE, type Destination, type DestinationDispatcher, type DestinationEvent, type DestinationResult, type DestinationsConfig, type DispatchResult, type DispatcherConfig, type GenerationResult, Post, type RssArticle, type SelectionState, type Session, type StorageConfig, type StylesConfig, type UploadResult, addCommentMark, applyCommentMarks, buildAutoDraftPrompt, buildChatPrompt, buildExpandPlanPrompt, buildGeneratePrompt, buildPlanPrompt, buildRewritePrompt, canDeleteComment, canEditComment, createAPIHandler, createAutoblogger, createCommentsClient, createCrudData, createDestinationDispatcher, createStorageHandler, detectStorageConfig, fetchRssFeeds, filterByKeywords, formatDate, generate, getDefaultModel, getModel, parseGeneratedContent, removeCommentMark, resolveModel, runAutoDraft, scrollToComment, truncate, uploadFile, validateSchema };
package/dist/index.d.ts CHANGED
@@ -743,6 +743,61 @@ declare function formatDate(date: Date | string, options?: Intl.DateTimeFormatOp
743
743
  */
744
744
  declare function truncate(text: string, maxLength: number): string;
745
745
 
746
+ /**
747
+ * Built-in storage module for autoblogger.
748
+ * Auto-detects cloud storage (S3-compatible) or falls back to local filesystem.
749
+ *
750
+ * Supported providers:
751
+ * - DigitalOcean Spaces (set SPACES_KEY, SPACES_SECRET)
752
+ * - AWS S3 (set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_S3_BUCKET)
753
+ * - Local filesystem (no config needed, saves to public/uploads)
754
+ */
755
+ interface UploadResult {
756
+ url: string;
757
+ key: string;
758
+ }
759
+ interface StorageConfig {
760
+ s3?: {
761
+ accessKeyId: string;
762
+ secretAccessKey: string;
763
+ bucket: string;
764
+ region?: string;
765
+ endpoint?: string;
766
+ cdnEndpoint?: string;
767
+ };
768
+ local?: {
769
+ uploadDir?: string;
770
+ urlPrefix?: string;
771
+ };
772
+ }
773
+ /**
774
+ * Detect storage configuration from environment variables
775
+ */
776
+ declare function detectStorageConfig(): StorageConfig;
777
+ /**
778
+ * Upload a file using auto-detected or provided storage config
779
+ */
780
+ declare function uploadFile(buffer: Buffer, filename: string, contentType: string, config?: StorageConfig): Promise<UploadResult>;
781
+ /**
782
+ * Create a storage upload handler for autoblogger config.
783
+ * Auto-detects cloud storage from env vars, falls back to local.
784
+ *
785
+ * Usage:
786
+ * ```ts
787
+ * import { createStorageHandler } from 'autoblogger'
788
+ *
789
+ * const cms = createAutoblogger({
790
+ * // ... other config
791
+ * storage: {
792
+ * upload: createStorageHandler()
793
+ * }
794
+ * })
795
+ * ```
796
+ */
797
+ declare function createStorageHandler(config?: StorageConfig): (file: File) => Promise<{
798
+ url: string;
799
+ }>;
800
+
746
801
  /**
747
802
  * Comment types and client-side API helpers for the editor commenting system.
748
803
  * Used for collaborative inline comments on posts.
@@ -819,4 +874,4 @@ declare function applyCommentMarks(editor: Editor, comments: CommentWithUser[]):
819
874
  */
820
875
  declare function scrollToComment(editor: Editor, commentId: string): void;
821
876
 
822
- export { type AIModel, AI_MODELS, type AutoDraftConfig, type AutobloggerServer as Autoblogger, type AutobloggerServerConfig as AutobloggerConfig, type BaseCrud, CommentMark, type CommentWithUser, type CreateCommentData, type CrudOptions, type CustomFieldConfig, type CustomFieldProps, DEFAULT_AUTO_DRAFT_TEMPLATE, DEFAULT_CHAT_TEMPLATE, DEFAULT_EXPAND_PLAN_TEMPLATE, DEFAULT_GENERATE_TEMPLATE, DEFAULT_PLAN_RULES, DEFAULT_PLAN_TEMPLATE, DEFAULT_REWRITE_TEMPLATE, type Destination, type DestinationDispatcher, type DestinationEvent, type DestinationResult, type DestinationsConfig, type DispatchResult, type DispatcherConfig, type GenerationResult, Post, type RssArticle, type SelectionState, type Session, type StylesConfig, addCommentMark, applyCommentMarks, buildAutoDraftPrompt, buildChatPrompt, buildExpandPlanPrompt, buildGeneratePrompt, buildPlanPrompt, buildRewritePrompt, canDeleteComment, canEditComment, createAPIHandler, createAutoblogger, createCommentsClient, createCrudData, createDestinationDispatcher, fetchRssFeeds, filterByKeywords, formatDate, generate, getDefaultModel, getModel, parseGeneratedContent, removeCommentMark, resolveModel, runAutoDraft, scrollToComment, truncate, validateSchema };
877
+ export { type AIModel, AI_MODELS, type AutoDraftConfig, type AutobloggerServer as Autoblogger, type AutobloggerServerConfig as AutobloggerConfig, type BaseCrud, CommentMark, type CommentWithUser, type CreateCommentData, type CrudOptions, type CustomFieldConfig, type CustomFieldProps, DEFAULT_AUTO_DRAFT_TEMPLATE, DEFAULT_CHAT_TEMPLATE, DEFAULT_EXPAND_PLAN_TEMPLATE, DEFAULT_GENERATE_TEMPLATE, DEFAULT_PLAN_RULES, DEFAULT_PLAN_TEMPLATE, DEFAULT_REWRITE_TEMPLATE, type Destination, type DestinationDispatcher, type DestinationEvent, type DestinationResult, type DestinationsConfig, type DispatchResult, type DispatcherConfig, type GenerationResult, Post, type RssArticle, type SelectionState, type Session, type StorageConfig, type StylesConfig, type UploadResult, addCommentMark, applyCommentMarks, buildAutoDraftPrompt, buildChatPrompt, buildExpandPlanPrompt, buildGeneratePrompt, buildPlanPrompt, buildRewritePrompt, canDeleteComment, canEditComment, createAPIHandler, createAutoblogger, createCommentsClient, createCrudData, createDestinationDispatcher, createStorageHandler, detectStorageConfig, fetchRssFeeds, filterByKeywords, formatDate, generate, getDefaultModel, getModel, parseGeneratedContent, removeCommentMark, resolveModel, runAutoDraft, scrollToComment, truncate, uploadFile, validateSchema };
package/dist/index.js CHANGED
@@ -4697,6 +4697,8 @@ __export(src_exports, {
4697
4697
  createCommentsClient: () => createCommentsClient,
4698
4698
  createCrudData: () => createCrudData,
4699
4699
  createDestinationDispatcher: () => createDestinationDispatcher,
4700
+ createStorageHandler: () => createStorageHandler,
4701
+ detectStorageConfig: () => detectStorageConfig,
4700
4702
  fetchRssFeeds: () => fetchRssFeeds,
4701
4703
  filterByKeywords: () => filterByKeywords,
4702
4704
  formatDate: () => formatDate,
@@ -4716,6 +4718,7 @@ __export(src_exports, {
4716
4718
  runAutoDraft: () => runAutoDraft,
4717
4719
  scrollToComment: () => scrollToComment,
4718
4720
  truncate: () => truncate,
4721
+ uploadFile: () => uploadFile,
4719
4722
  validateSchema: () => validateSchema,
4720
4723
  wordCount: () => wordCount
4721
4724
  });
@@ -7074,6 +7077,95 @@ function createDestinationDispatcher(config) {
7074
7077
  };
7075
7078
  }
7076
7079
 
7080
+ // src/lib/storage.ts
7081
+ var import_promises = require("fs/promises");
7082
+ var import_path = require("path");
7083
+ var import_crypto = require("crypto");
7084
+ var s3ClientPromise = null;
7085
+ async function getS3Client(config) {
7086
+ if (!s3ClientPromise) {
7087
+ s3ClientPromise = (async () => {
7088
+ const { S3Client } = await Function('return import("@aws-sdk/client-s3")')();
7089
+ return new S3Client({
7090
+ region: config.region || "us-east-1",
7091
+ endpoint: config.endpoint,
7092
+ credentials: {
7093
+ accessKeyId: config.accessKeyId,
7094
+ secretAccessKey: config.secretAccessKey
7095
+ }
7096
+ });
7097
+ })();
7098
+ }
7099
+ return s3ClientPromise;
7100
+ }
7101
+ async function uploadToS3(buffer, filename, contentType, config) {
7102
+ const { PutObjectCommand } = await Function('return import("@aws-sdk/client-s3")')();
7103
+ const client = await getS3Client(config);
7104
+ const ext = filename.split(".").pop()?.toLowerCase() || "jpg";
7105
+ const key = `uploads/${(0, import_crypto.randomUUID)()}.${ext}`;
7106
+ await client.send(
7107
+ new PutObjectCommand({
7108
+ Bucket: config.bucket,
7109
+ Key: key,
7110
+ Body: buffer,
7111
+ ContentType: contentType,
7112
+ ACL: "public-read"
7113
+ })
7114
+ );
7115
+ const cdnEndpoint = config.cdnEndpoint || config.endpoint || `https://${config.bucket}.s3.${config.region || "us-east-1"}.amazonaws.com`;
7116
+ const url = cdnEndpoint.endsWith("/") ? `${cdnEndpoint}${key}` : `${cdnEndpoint}/${key}`;
7117
+ return { url, key };
7118
+ }
7119
+ async function uploadToLocal(buffer, filename, config) {
7120
+ const ext = filename.split(".").pop()?.toLowerCase() || "jpg";
7121
+ const key = `${(0, import_crypto.randomUUID)()}.${ext}`;
7122
+ const uploadDir = config?.uploadDir || (0, import_path.join)(process.cwd(), "public", "uploads");
7123
+ const urlPrefix = config?.urlPrefix || "/uploads";
7124
+ await (0, import_promises.mkdir)(uploadDir, { recursive: true });
7125
+ await (0, import_promises.writeFile)((0, import_path.join)(uploadDir, key), buffer);
7126
+ return { url: `${urlPrefix}/${key}`, key };
7127
+ }
7128
+ function detectStorageConfig() {
7129
+ if (process.env.SPACES_KEY && process.env.SPACES_SECRET) {
7130
+ return {
7131
+ s3: {
7132
+ accessKeyId: process.env.SPACES_KEY,
7133
+ secretAccessKey: process.env.SPACES_SECRET,
7134
+ bucket: process.env.SPACES_BUCKET || "uploads",
7135
+ region: process.env.SPACES_REGION || "sfo3",
7136
+ endpoint: process.env.SPACES_ENDPOINT || `https://${process.env.SPACES_REGION || "sfo3"}.digitaloceanspaces.com`,
7137
+ cdnEndpoint: process.env.SPACES_CDN_ENDPOINT
7138
+ }
7139
+ };
7140
+ }
7141
+ if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY && process.env.AWS_S3_BUCKET) {
7142
+ return {
7143
+ s3: {
7144
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
7145
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
7146
+ bucket: process.env.AWS_S3_BUCKET,
7147
+ region: process.env.AWS_REGION || "us-east-1",
7148
+ cdnEndpoint: process.env.AWS_S3_CDN_ENDPOINT
7149
+ }
7150
+ };
7151
+ }
7152
+ return { local: {} };
7153
+ }
7154
+ async function uploadFile(buffer, filename, contentType, config) {
7155
+ const resolvedConfig = config || detectStorageConfig();
7156
+ if (resolvedConfig.s3) {
7157
+ return uploadToS3(buffer, filename, contentType, resolvedConfig.s3);
7158
+ }
7159
+ return uploadToLocal(buffer, filename, resolvedConfig.local);
7160
+ }
7161
+ function createStorageHandler(config) {
7162
+ return async (file) => {
7163
+ const buffer = Buffer.from(await file.arrayBuffer());
7164
+ const result = await uploadFile(buffer, file.name, file.type, config);
7165
+ return { url: result.url };
7166
+ };
7167
+ }
7168
+
7077
7169
  // src/types/config.ts
7078
7170
  var DEFAULT_STYLES = {
7079
7171
  container: "max-w-ab-content mx-auto px-ab-content-padding",
@@ -7090,6 +7182,9 @@ function createAutoblogger(config) {
7090
7182
  ...DEFAULT_STYLES,
7091
7183
  ...config.styles
7092
7184
  };
7185
+ const storage = config.storage || {
7186
+ upload: createStorageHandler()
7187
+ };
7093
7188
  const dispatcher = createDestinationDispatcher({
7094
7189
  destinations: config.destinations,
7095
7190
  webhooks: config.webhooks,
@@ -7100,6 +7195,7 @@ function createAutoblogger(config) {
7100
7195
  const baseServer = {
7101
7196
  config: {
7102
7197
  ...config,
7198
+ storage,
7103
7199
  styles: mergedStyles
7104
7200
  },
7105
7201
  posts: createPostsData(prisma, config.hooks, dispatcher, config.prismic?.writeToken),
@@ -11490,6 +11586,8 @@ function scrollToComment(editor, commentId) {
11490
11586
  createCommentsClient,
11491
11587
  createCrudData,
11492
11588
  createDestinationDispatcher,
11589
+ createStorageHandler,
11590
+ detectStorageConfig,
11493
11591
  fetchRssFeeds,
11494
11592
  filterByKeywords,
11495
11593
  formatDate,
@@ -11509,6 +11607,7 @@ function scrollToComment(editor, commentId) {
11509
11607
  runAutoDraft,
11510
11608
  scrollToComment,
11511
11609
  truncate,
11610
+ uploadFile,
11512
11611
  validateSchema,
11513
11612
  wordCount
11514
11613
  });