@bernierllc/content-storage-adapter 1.0.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 (54) hide show
  1. package/.eslintrc.json +22 -0
  2. package/README.md +350 -0
  3. package/__tests__/ContentBatchOperations.test.ts +130 -0
  4. package/__tests__/ContentStorageAdapter.test.ts +604 -0
  5. package/__tests__/mocks/MockDatabaseAdapter.test.ts +97 -0
  6. package/__tests__/mocks/MockDatabaseAdapter.ts +85 -0
  7. package/dist/ContentBatchOperations.d.ts +22 -0
  8. package/dist/ContentBatchOperations.d.ts.map +1 -0
  9. package/dist/ContentBatchOperations.js +60 -0
  10. package/dist/ContentBatchOperations.js.map +1 -0
  11. package/dist/ContentStorageAdapter.d.ts +75 -0
  12. package/dist/ContentStorageAdapter.d.ts.map +1 -0
  13. package/dist/ContentStorageAdapter.js +382 -0
  14. package/dist/ContentStorageAdapter.js.map +1 -0
  15. package/dist/errors/ContentNotFoundError.d.ts +7 -0
  16. package/dist/errors/ContentNotFoundError.d.ts.map +1 -0
  17. package/dist/errors/ContentNotFoundError.js +21 -0
  18. package/dist/errors/ContentNotFoundError.js.map +1 -0
  19. package/dist/errors/DuplicateSlugError.d.ts +7 -0
  20. package/dist/errors/DuplicateSlugError.d.ts.map +1 -0
  21. package/dist/errors/DuplicateSlugError.js +21 -0
  22. package/dist/errors/DuplicateSlugError.js.map +1 -0
  23. package/dist/errors/OptimisticLockError.d.ts +7 -0
  24. package/dist/errors/OptimisticLockError.d.ts.map +1 -0
  25. package/dist/errors/OptimisticLockError.js +21 -0
  26. package/dist/errors/OptimisticLockError.js.map +1 -0
  27. package/dist/index.d.ts +10 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +27 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/models/IContent.d.ts +92 -0
  32. package/dist/models/IContent.d.ts.map +1 -0
  33. package/dist/models/IContent.js +42 -0
  34. package/dist/models/IContent.js.map +1 -0
  35. package/dist/models/IContentFilters.d.ts +29 -0
  36. package/dist/models/IContentFilters.d.ts.map +1 -0
  37. package/dist/models/IContentFilters.js +10 -0
  38. package/dist/models/IContentFilters.js.map +1 -0
  39. package/dist/models/IContentVersion.d.ts +15 -0
  40. package/dist/models/IContentVersion.d.ts.map +1 -0
  41. package/dist/models/IContentVersion.js +10 -0
  42. package/dist/models/IContentVersion.js.map +1 -0
  43. package/jest.config.cjs +30 -0
  44. package/package.json +38 -0
  45. package/src/ContentBatchOperations.ts +72 -0
  46. package/src/ContentStorageAdapter.ts +476 -0
  47. package/src/errors/ContentNotFoundError.ts +17 -0
  48. package/src/errors/DuplicateSlugError.ts +17 -0
  49. package/src/errors/OptimisticLockError.ts +17 -0
  50. package/src/index.ts +33 -0
  51. package/src/models/IContent.ts +122 -0
  52. package/src/models/IContentFilters.ts +38 -0
  53. package/src/models/IContentVersion.ts +22 -0
  54. package/tsconfig.json +26 -0
@@ -0,0 +1,85 @@
1
+ /*
2
+ Copyright (c) 2025 Bernier LLC
3
+
4
+ This file is licensed to the client under a limited-use license.
5
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
6
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
7
+ */
8
+
9
+ import { IDatabaseAdapter, IQueryResult } from '@bernierllc/database-adapter-core';
10
+
11
+ /**
12
+ * Mock database adapter for testing
13
+ */
14
+ export class MockDatabaseAdapter implements IDatabaseAdapter {
15
+ private queryResults: Map<string, IQueryResult<Record<string, unknown>>> = new Map();
16
+ private connected = false;
17
+
18
+ async connect(): Promise<void> {
19
+ this.connected = true;
20
+ }
21
+
22
+ async disconnect(): Promise<void> {
23
+ this.connected = false;
24
+ }
25
+
26
+ async query<T = Record<string, unknown>>(
27
+ sql: string,
28
+ _params?: unknown[]
29
+ ): Promise<IQueryResult<T>> {
30
+ if (!this.connected) {
31
+ throw new Error('Database not connected');
32
+ }
33
+
34
+ // Find matching mock result
35
+ const key = this.generateKey(sql);
36
+ const result = this.queryResults.get(key);
37
+
38
+ if (!result) {
39
+ // Return empty result for unregistered queries
40
+ return {
41
+ rows: [],
42
+ rowCount: 0
43
+ } as IQueryResult<T>;
44
+ }
45
+
46
+ return result as IQueryResult<T>;
47
+ }
48
+
49
+ async beginTransaction(): Promise<void> {
50
+ // Mock implementation
51
+ }
52
+
53
+ async commit(): Promise<void> {
54
+ // Mock implementation
55
+ }
56
+
57
+ async rollback(): Promise<void> {
58
+ // Mock implementation
59
+ }
60
+
61
+ /**
62
+ * Set mock result for a query pattern
63
+ */
64
+ setQueryResult<T = Record<string, unknown>>(
65
+ sqlPattern: string,
66
+ result: IQueryResult<T>
67
+ ): void {
68
+ const key = this.generateKey(sqlPattern);
69
+ this.queryResults.set(key, result as IQueryResult<Record<string, unknown>>);
70
+ }
71
+
72
+ /**
73
+ * Clear all mock results
74
+ */
75
+ clearMocks(): void {
76
+ this.queryResults.clear();
77
+ }
78
+
79
+ /**
80
+ * Generate key from SQL pattern (normalize whitespace)
81
+ */
82
+ private generateKey(sql: string): string {
83
+ return sql.replace(/\s+/g, ' ').trim().toLowerCase();
84
+ }
85
+ }
@@ -0,0 +1,22 @@
1
+ import { ContentStorageAdapter } from './ContentStorageAdapter';
2
+ import { ContentStatus } from './models/IContent';
3
+ /**
4
+ * Batch operations for content management
5
+ */
6
+ export declare class ContentBatchOperations {
7
+ private adapter;
8
+ constructor(adapter: ContentStorageAdapter);
9
+ /**
10
+ * Bulk update status for multiple content items
11
+ */
12
+ bulkUpdateStatus(ids: string[], status: ContentStatus): Promise<number>;
13
+ /**
14
+ * Bulk soft delete
15
+ */
16
+ bulkDelete(ids: string[]): Promise<number>;
17
+ /**
18
+ * Bulk restore
19
+ */
20
+ bulkRestore(ids: string[]): Promise<number>;
21
+ }
22
+ //# sourceMappingURL=ContentBatchOperations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentBatchOperations.d.ts","sourceRoot":"","sources":["../src/ContentBatchOperations.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD;;GAEG;AACH,qBAAa,sBAAsB;IACrB,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,qBAAqB;IAElD;;OAEG;IACG,gBAAgB,CACpB,GAAG,EAAE,MAAM,EAAE,EACb,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC;IAelB;;OAEG;IACG,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAchD;;OAEG;IACG,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAalD"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ContentBatchOperations = void 0;
11
+ /**
12
+ * Batch operations for content management
13
+ */
14
+ class ContentBatchOperations {
15
+ constructor(adapter) {
16
+ this.adapter = adapter;
17
+ }
18
+ /**
19
+ * Bulk update status for multiple content items
20
+ */
21
+ async bulkUpdateStatus(ids, status) {
22
+ let updated = 0;
23
+ for (const id of ids) {
24
+ try {
25
+ await this.adapter.update(id, { status });
26
+ updated++;
27
+ }
28
+ catch (error) {
29
+ // Continue on individual failures
30
+ }
31
+ }
32
+ return updated;
33
+ }
34
+ /**
35
+ * Bulk soft delete
36
+ */
37
+ async bulkDelete(ids) {
38
+ const db = this.adapter.db;
39
+ const result = await db.query(`
40
+ UPDATE content
41
+ SET deleted_at = NOW()
42
+ WHERE id = ANY($1) AND deleted_at IS NULL
43
+ `, [ids]);
44
+ return result.rowCount;
45
+ }
46
+ /**
47
+ * Bulk restore
48
+ */
49
+ async bulkRestore(ids) {
50
+ const db = this.adapter.db;
51
+ const result = await db.query(`
52
+ UPDATE content
53
+ SET deleted_at = NULL
54
+ WHERE id = ANY($1) AND deleted_at IS NOT NULL
55
+ `, [ids]);
56
+ return result.rowCount;
57
+ }
58
+ }
59
+ exports.ContentBatchOperations = ContentBatchOperations;
60
+ //# sourceMappingURL=ContentBatchOperations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentBatchOperations.js","sourceRoot":"","sources":["../src/ContentBatchOperations.ts"],"names":[],"mappings":";AAAA;;;;;;EAME;;;AAKF;;GAEG;AACH,MAAa,sBAAsB;IACjC,YAAoB,OAA8B;QAA9B,YAAO,GAAP,OAAO,CAAuB;IAAG,CAAC;IAEtD;;OAEG;IACH,KAAK,CAAC,gBAAgB,CACpB,GAAa,EACb,MAAqB;QAErB,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC1C,OAAO,EAAE,CAAC;YACZ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,kCAAkC;YACpC,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,GAAa;QAC5B,MAAM,EAAE,GAAI,IAAI,CAAC,OAA2G,CAAC,EAAE,CAAC;QAChI,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAC3B;;;;OAIC,EACD,CAAC,GAAG,CAAC,CACN,CAAC;QAEF,OAAO,MAAM,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,GAAa;QAC7B,MAAM,EAAE,GAAI,IAAI,CAAC,OAA2G,CAAC,EAAE,CAAC;QAChI,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,CAC3B;;;;OAIC,EACD,CAAC,GAAG,CAAC,CACN,CAAC;QAEF,OAAO,MAAM,CAAC,QAAQ,CAAC;IACzB,CAAC;CACF;AAzDD,wDAyDC"}
@@ -0,0 +1,75 @@
1
+ import { IDatabaseAdapter } from '@bernierllc/database-adapter-core';
2
+ import { IContent, IContentCreateData, IContentUpdateData } from './models/IContent';
3
+ import { IContentVersion } from './models/IContentVersion';
4
+ import { IContentFilters, IPaginatedResult } from './models/IContentFilters';
5
+ /**
6
+ * Content storage adapter
7
+ * Provides type-safe CRUD operations for content management
8
+ */
9
+ export declare class ContentStorageAdapter {
10
+ private db;
11
+ constructor(db: IDatabaseAdapter);
12
+ /**
13
+ * Create new content with automatic slug generation
14
+ */
15
+ create(data: IContentCreateData): Promise<IContent>;
16
+ /**
17
+ * Get content by ID (with soft-delete check)
18
+ */
19
+ getById(id: string, options?: {
20
+ includeDeleted?: boolean;
21
+ }): Promise<IContent | null>;
22
+ /**
23
+ * Get content by slug
24
+ */
25
+ getBySlug(slug: string): Promise<IContent | null>;
26
+ /**
27
+ * Update content with optimistic locking
28
+ */
29
+ update(id: string, data: IContentUpdateData, expectedUpdatedAt?: Date): Promise<IContent>;
30
+ /**
31
+ * Soft delete content
32
+ */
33
+ delete(id: string): Promise<void>;
34
+ /**
35
+ * Permanently delete content (use sparingly)
36
+ */
37
+ hardDelete(id: string): Promise<void>;
38
+ /**
39
+ * Restore soft-deleted content
40
+ */
41
+ restore(id: string): Promise<IContent>;
42
+ /**
43
+ * List content with filters and pagination
44
+ */
45
+ list(filters?: IContentFilters): Promise<IPaginatedResult<IContent>>;
46
+ /**
47
+ * Get content versions
48
+ */
49
+ getVersions(contentId: string): Promise<IContentVersion[]>;
50
+ /**
51
+ * Get specific version
52
+ */
53
+ getVersion(contentId: string, versionNumber: number): Promise<IContentVersion | null>;
54
+ /**
55
+ * Ensure slug is unique by appending number if needed
56
+ */
57
+ private ensureUniqueSlug;
58
+ /**
59
+ * Check if slug exists
60
+ */
61
+ private slugExists;
62
+ /**
63
+ * Map database row to content model
64
+ */
65
+ private mapRowToContent;
66
+ /**
67
+ * Map database row to version model
68
+ */
69
+ private mapRowToVersion;
70
+ /**
71
+ * Map order field to database column
72
+ */
73
+ private mapOrderField;
74
+ }
75
+ //# sourceMappingURL=ContentStorageAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentStorageAdapter.d.ts","sourceRoot":"","sources":["../src/ContentStorageAdapter.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAErE,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,kBAAkB,EAInB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAI7E;;;GAGG;AACH,qBAAa,qBAAqB;IACpB,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,gBAAgB;IAExC;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAsCzD;;OAEG;IACG,OAAO,CACX,EAAE,EAAE,MAAM,EACV,OAAO,GAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAO,GACzC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAe3B;;OAEG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAWvD;;OAEG;IACG,MAAM,CACV,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,kBAAkB,EACxB,iBAAiB,CAAC,EAAE,IAAI,GACvB,OAAO,CAAC,QAAQ,CAAC;IAoFpB;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAevC;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C;;OAEG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAkB5C;;OAEG;IACG,IAAI,CACR,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAqGtC;;OAEG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAahE;;OAEG;IACG,UAAU,CACd,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAclC;;OAEG;YACW,gBAAgB;IAY9B;;OAEG;YACW,UAAU;IAQxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAgCvB;;OAEG;IACH,OAAO,CAAC,eAAe;IAcvB;;OAEG;IACH,OAAO,CAAC,aAAa;CAStB"}
@@ -0,0 +1,382 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ContentStorageAdapter = void 0;
11
+ const slug_generator_1 = require("@bernierllc/slug-generator");
12
+ const IContent_1 = require("./models/IContent");
13
+ const ContentNotFoundError_1 = require("./errors/ContentNotFoundError");
14
+ const OptimisticLockError_1 = require("./errors/OptimisticLockError");
15
+ /**
16
+ * Content storage adapter
17
+ * Provides type-safe CRUD operations for content management
18
+ */
19
+ class ContentStorageAdapter {
20
+ constructor(db) {
21
+ this.db = db;
22
+ }
23
+ /**
24
+ * Create new content with automatic slug generation
25
+ */
26
+ async create(data) {
27
+ // Generate unique slug from title
28
+ const baseSlug = (0, slug_generator_1.generateSlug)(data.title);
29
+ const slug = await this.ensureUniqueSlug(baseSlug);
30
+ const result = await this.db.query(`
31
+ INSERT INTO content (
32
+ user_id, title, slug, body, excerpt, type, format, status,
33
+ meta_title, meta_description, keywords,
34
+ ai_reviewed, view_count, share_count, generated_from_commit
35
+ ) VALUES (
36
+ $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15
37
+ )
38
+ RETURNING *
39
+ `, [
40
+ data.userId,
41
+ data.title,
42
+ slug,
43
+ data.body,
44
+ data.excerpt || null,
45
+ data.type || IContent_1.ContentType.BLOG,
46
+ data.format || IContent_1.ContentFormat.MARKDOWN,
47
+ data.status || IContent_1.ContentStatus.DRAFT,
48
+ data.metaTitle || null,
49
+ data.metaDescription || null,
50
+ data.keywords || [],
51
+ false, // ai_reviewed
52
+ 0, // view_count
53
+ 0, // share_count
54
+ false // generated_from_commit
55
+ ]);
56
+ return this.mapRowToContent(result.rows[0]);
57
+ }
58
+ /**
59
+ * Get content by ID (with soft-delete check)
60
+ */
61
+ async getById(id, options = {}) {
62
+ const whereClause = options.includeDeleted
63
+ ? 'id = $1'
64
+ : 'id = $1 AND deleted_at IS NULL';
65
+ const result = await this.db.query(`SELECT * FROM content WHERE ${whereClause}`, [id]);
66
+ return result.rows.length > 0
67
+ ? this.mapRowToContent(result.rows[0])
68
+ : null;
69
+ }
70
+ /**
71
+ * Get content by slug
72
+ */
73
+ async getBySlug(slug) {
74
+ const result = await this.db.query('SELECT * FROM content WHERE slug = $1 AND deleted_at IS NULL', [slug]);
75
+ return result.rows.length > 0
76
+ ? this.mapRowToContent(result.rows[0])
77
+ : null;
78
+ }
79
+ /**
80
+ * Update content with optimistic locking
81
+ */
82
+ async update(id, data, expectedUpdatedAt) {
83
+ // Build dynamic UPDATE query
84
+ const updates = [];
85
+ const params = [];
86
+ let paramIndex = 1;
87
+ if (data.title !== undefined) {
88
+ updates.push(`title = $${paramIndex++}`);
89
+ params.push(data.title);
90
+ }
91
+ if (data.body !== undefined) {
92
+ updates.push(`body = $${paramIndex++}`);
93
+ params.push(data.body);
94
+ }
95
+ if (data.excerpt !== undefined) {
96
+ updates.push(`excerpt = $${paramIndex++}`);
97
+ params.push(data.excerpt);
98
+ }
99
+ if (data.status !== undefined) {
100
+ updates.push(`status = $${paramIndex++}`);
101
+ params.push(data.status);
102
+ }
103
+ if (data.workflowStage !== undefined) {
104
+ updates.push(`workflow_stage = $${paramIndex++}`);
105
+ params.push(data.workflowStage);
106
+ }
107
+ if (data.assignedTo !== undefined) {
108
+ updates.push(`assigned_to = $${paramIndex++}`);
109
+ params.push(data.assignedTo);
110
+ }
111
+ if (data.publishedAt !== undefined) {
112
+ updates.push(`published_at = $${paramIndex++}`);
113
+ params.push(data.publishedAt);
114
+ }
115
+ if (data.scheduledFor !== undefined) {
116
+ updates.push(`scheduled_for = $${paramIndex++}`);
117
+ params.push(data.scheduledFor);
118
+ }
119
+ if (data.metaTitle !== undefined) {
120
+ updates.push(`meta_title = $${paramIndex++}`);
121
+ params.push(data.metaTitle);
122
+ }
123
+ if (data.metaDescription !== undefined) {
124
+ updates.push(`meta_description = $${paramIndex++}`);
125
+ params.push(data.metaDescription);
126
+ }
127
+ if (data.keywords !== undefined) {
128
+ updates.push(`keywords = $${paramIndex++}`);
129
+ params.push(data.keywords);
130
+ }
131
+ if (updates.length === 0) {
132
+ throw new Error('No fields to update');
133
+ }
134
+ // Add optimistic locking check
135
+ params.push(id);
136
+ const idParam = paramIndex++;
137
+ let whereClause = `id = $${idParam} AND deleted_at IS NULL`;
138
+ if (expectedUpdatedAt) {
139
+ params.push(expectedUpdatedAt);
140
+ whereClause += ` AND updated_at = $${paramIndex++}`;
141
+ }
142
+ const sql = `
143
+ UPDATE content
144
+ SET ${updates.join(', ')}, updated_at = NOW()
145
+ WHERE ${whereClause}
146
+ RETURNING *
147
+ `;
148
+ const result = await this.db.query(sql, params);
149
+ if (result.rows.length === 0) {
150
+ if (expectedUpdatedAt) {
151
+ throw new OptimisticLockError_1.OptimisticLockError(id);
152
+ }
153
+ throw new ContentNotFoundError_1.ContentNotFoundError(id);
154
+ }
155
+ return this.mapRowToContent(result.rows[0]);
156
+ }
157
+ /**
158
+ * Soft delete content
159
+ */
160
+ async delete(id) {
161
+ const result = await this.db.query(`
162
+ UPDATE content
163
+ SET deleted_at = NOW()
164
+ WHERE id = $1 AND deleted_at IS NULL
165
+ `, [id]);
166
+ if (result.rowCount === 0) {
167
+ throw new ContentNotFoundError_1.ContentNotFoundError(id);
168
+ }
169
+ }
170
+ /**
171
+ * Permanently delete content (use sparingly)
172
+ */
173
+ async hardDelete(id) {
174
+ await this.db.query('DELETE FROM content WHERE id = $1', [id]);
175
+ }
176
+ /**
177
+ * Restore soft-deleted content
178
+ */
179
+ async restore(id) {
180
+ const result = await this.db.query(`
181
+ UPDATE content
182
+ SET deleted_at = NULL
183
+ WHERE id = $1 AND deleted_at IS NOT NULL
184
+ RETURNING *
185
+ `, [id]);
186
+ if (result.rows.length === 0) {
187
+ throw new Error('Content not found or not deleted');
188
+ }
189
+ return this.mapRowToContent(result.rows[0]);
190
+ }
191
+ /**
192
+ * List content with filters and pagination
193
+ */
194
+ async list(filters = {}) {
195
+ // Build WHERE clause
196
+ const conditions = [];
197
+ const params = [];
198
+ let paramIndex = 1;
199
+ if (!filters.includeDeleted) {
200
+ conditions.push('deleted_at IS NULL');
201
+ }
202
+ if (filters.userId) {
203
+ conditions.push(`user_id = $${paramIndex++}`);
204
+ params.push(filters.userId);
205
+ }
206
+ if (filters.status) {
207
+ if (Array.isArray(filters.status)) {
208
+ conditions.push(`status = ANY($${paramIndex++})`);
209
+ params.push(filters.status);
210
+ }
211
+ else {
212
+ conditions.push(`status = $${paramIndex++}`);
213
+ params.push(filters.status);
214
+ }
215
+ }
216
+ if (filters.type) {
217
+ if (Array.isArray(filters.type)) {
218
+ conditions.push(`type = ANY($${paramIndex++})`);
219
+ params.push(filters.type);
220
+ }
221
+ else {
222
+ conditions.push(`type = $${paramIndex++}`);
223
+ params.push(filters.type);
224
+ }
225
+ }
226
+ if (filters.workflowStage) {
227
+ conditions.push(`workflow_stage = $${paramIndex++}`);
228
+ params.push(filters.workflowStage);
229
+ }
230
+ if (filters.publishedAfter) {
231
+ conditions.push(`published_at >= $${paramIndex++}`);
232
+ params.push(filters.publishedAfter);
233
+ }
234
+ if (filters.publishedBefore) {
235
+ conditions.push(`published_at <= $${paramIndex++}`);
236
+ params.push(filters.publishedBefore);
237
+ }
238
+ if (filters.searchQuery) {
239
+ conditions.push(`(
240
+ title ILIKE $${paramIndex} OR
241
+ body ILIKE $${paramIndex} OR
242
+ excerpt ILIKE $${paramIndex}
243
+ )`);
244
+ params.push(`%${filters.searchQuery}%`);
245
+ paramIndex++;
246
+ }
247
+ const whereClause = conditions.length > 0
248
+ ? `WHERE ${conditions.join(' AND ')}`
249
+ : '';
250
+ // Build ORDER BY
251
+ const orderBy = filters.orderBy || 'createdAt';
252
+ const orderDirection = filters.orderDirection || 'DESC';
253
+ const orderClause = `ORDER BY ${this.mapOrderField(orderBy)} ${orderDirection}`;
254
+ // Pagination
255
+ const limit = filters.limit || 20;
256
+ const offset = filters.offset || 0;
257
+ // Get total count
258
+ const countResult = await this.db.query(`SELECT COUNT(*) as count FROM content ${whereClause}`, params);
259
+ const total = parseInt(countResult.rows[0].count);
260
+ // Get data
261
+ params.push(limit, offset);
262
+ const dataResult = await this.db.query(`
263
+ SELECT * FROM content
264
+ ${whereClause}
265
+ ${orderClause}
266
+ LIMIT $${paramIndex++} OFFSET $${paramIndex++}
267
+ `, params);
268
+ return {
269
+ data: dataResult.rows.map(row => this.mapRowToContent(row)),
270
+ total,
271
+ limit,
272
+ offset,
273
+ hasMore: offset + limit < total
274
+ };
275
+ }
276
+ /**
277
+ * Get content versions
278
+ */
279
+ async getVersions(contentId) {
280
+ const result = await this.db.query(`
281
+ SELECT * FROM content_versions
282
+ WHERE content_id = $1
283
+ ORDER BY version_number DESC
284
+ `, [contentId]);
285
+ return result.rows.map(row => this.mapRowToVersion(row));
286
+ }
287
+ /**
288
+ * Get specific version
289
+ */
290
+ async getVersion(contentId, versionNumber) {
291
+ const result = await this.db.query(`
292
+ SELECT * FROM content_versions
293
+ WHERE content_id = $1 AND version_number = $2
294
+ `, [contentId, versionNumber]);
295
+ return result.rows.length > 0
296
+ ? this.mapRowToVersion(result.rows[0])
297
+ : null;
298
+ }
299
+ /**
300
+ * Ensure slug is unique by appending number if needed
301
+ */
302
+ async ensureUniqueSlug(baseSlug) {
303
+ let slug = baseSlug;
304
+ let counter = 1;
305
+ while (await this.slugExists(slug)) {
306
+ slug = `${baseSlug}-${counter}`;
307
+ counter++;
308
+ }
309
+ return slug;
310
+ }
311
+ /**
312
+ * Check if slug exists
313
+ */
314
+ async slugExists(slug) {
315
+ const result = await this.db.query('SELECT EXISTS(SELECT 1 FROM content WHERE slug = $1 AND deleted_at IS NULL) as exists', [slug]);
316
+ return result.rows[0].exists;
317
+ }
318
+ /**
319
+ * Map database row to content model
320
+ */
321
+ mapRowToContent(row) {
322
+ return {
323
+ id: row.id,
324
+ userId: row.user_id,
325
+ title: row.title,
326
+ slug: row.slug,
327
+ body: row.body,
328
+ excerpt: row.excerpt,
329
+ type: row.type,
330
+ format: row.format,
331
+ status: row.status,
332
+ workflowStage: row.workflow_stage,
333
+ assignedTo: row.assigned_to,
334
+ aiReviewed: row.ai_reviewed,
335
+ aiReviewScore: row.ai_review_score,
336
+ aiProvider: row.ai_provider,
337
+ publishedAt: row.published_at,
338
+ scheduledFor: row.scheduled_for,
339
+ deletedAt: row.deleted_at,
340
+ metaTitle: row.meta_title,
341
+ metaDescription: row.meta_description,
342
+ keywords: row.keywords,
343
+ viewCount: row.view_count,
344
+ shareCount: row.share_count,
345
+ generatedFromCommit: row.generated_from_commit,
346
+ sourceCommitSha: row.source_commit_sha,
347
+ sourceRepository: row.source_repository,
348
+ createdAt: row.created_at,
349
+ updatedAt: row.updated_at
350
+ };
351
+ }
352
+ /**
353
+ * Map database row to version model
354
+ */
355
+ mapRowToVersion(row) {
356
+ return {
357
+ id: row.id,
358
+ contentId: row.content_id,
359
+ versionNumber: row.version_number,
360
+ title: row.title,
361
+ body: row.body,
362
+ changeSummary: row.change_summary,
363
+ isAutosave: row.is_autosave,
364
+ createdAt: row.created_at,
365
+ createdBy: row.created_by
366
+ };
367
+ }
368
+ /**
369
+ * Map order field to database column
370
+ */
371
+ mapOrderField(field) {
372
+ const fieldMap = {
373
+ createdAt: 'created_at',
374
+ updatedAt: 'updated_at',
375
+ publishedAt: 'published_at',
376
+ title: 'title'
377
+ };
378
+ return fieldMap[field] || 'created_at';
379
+ }
380
+ }
381
+ exports.ContentStorageAdapter = ContentStorageAdapter;
382
+ //# sourceMappingURL=ContentStorageAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentStorageAdapter.js","sourceRoot":"","sources":["../src/ContentStorageAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Error thrown when content is not found
3
+ */
4
+ export declare class ContentNotFoundError extends Error {
5
+ constructor(id: string);
6
+ }
7
+ //# sourceMappingURL=ContentNotFoundError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentNotFoundError.d.ts","sourceRoot":"","sources":["../../src/errors/ContentNotFoundError.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,EAAE,EAAE,MAAM;CAIvB"}