@content-streamline/nextjs 0.0.4 → 0.0.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,IAAI,EACJ,kBAAkB,EAClB,aAAa,EACd,MAAM,mBAAmB,CAAC;AAE3B,cAAM,oBAAoB;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;YAKlC,KAAK;IAiCnB;;OAEG;IACG,SAAS,CAAC,IAAI,GAAE,MAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAS5E;;OAEG;IACG,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAgBrD;;OAEG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,aAAa,GAAE,UAAU,GAAG,MAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAIxG;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,oBAAoB,CAE1F"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,IAAI,EACJ,kBAAkB,EAClB,aAAa,EACd,MAAM,mBAAmB,CAAC;AAE3B,cAAM,oBAAoB;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;YAKlC,KAAK;IAsDnB;;OAEG;IACG,SAAS,CAAC,IAAI,GAAE,MAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAS5E;;OAEG;IACG,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IA4BrD;;OAEG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,aAAa,GAAE,UAAU,GAAG,MAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAIxG;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,oBAAoB,CAE1F"}
@@ -13,14 +13,31 @@ class ContentStreamlineAPI {
13
13
  'Content-Type': 'application/json',
14
14
  ...options.headers,
15
15
  };
16
- const response = await fetch(url, {
17
- ...options,
18
- headers,
19
- });
16
+ let response;
17
+ try {
18
+ response = await fetch(url, {
19
+ ...options,
20
+ headers,
21
+ });
22
+ }
23
+ catch (error) {
24
+ // Network error (connection failed, timeout, etc.)
25
+ const errorMessage = error instanceof Error ? error.message : String(error);
26
+ throw new Error(`Network error: ${errorMessage}`);
27
+ }
20
28
  if (!response.ok) {
21
- if (response.status === 401) {
29
+ let errorMessage = `API request failed: ${response.status} ${response.statusText}`;
30
+ try {
22
31
  const errorText = await response.text();
23
- if (errorText.includes('Missing access token')) {
32
+ if (errorText) {
33
+ errorMessage += ` - ${errorText}`;
34
+ }
35
+ }
36
+ catch {
37
+ // Ignore error reading response body
38
+ }
39
+ if (response.status === 401) {
40
+ if (errorMessage.includes('Missing access token')) {
24
41
  throw new Error('Missing access token');
25
42
  }
26
43
  throw new Error('Invalid access token');
@@ -31,9 +48,15 @@ class ContentStreamlineAPI {
31
48
  if (response.status === 404) {
32
49
  throw new Error('Post not found');
33
50
  }
34
- throw new Error(`API request failed: ${response.status} ${response.statusText}`);
51
+ throw new Error(errorMessage);
52
+ }
53
+ try {
54
+ const data = await response.json();
55
+ return data;
56
+ }
57
+ catch (error) {
58
+ throw new Error(`Failed to parse API response as JSON: ${error instanceof Error ? error.message : String(error)}`);
35
59
  }
36
- return response.json();
37
60
  }
38
61
  /**
39
62
  * List all posts with pagination
@@ -55,9 +78,18 @@ class ContentStreamlineAPI {
55
78
  let hasMore = true;
56
79
  while (hasMore) {
57
80
  const response = await this.listPosts(currentPage, platform);
81
+ // Validate response structure
82
+ if (!response || !Array.isArray(response.data)) {
83
+ throw new Error(`Invalid API response: expected PostsResponse with data array, got ${typeof response}`);
84
+ }
58
85
  allPosts.push(...response.data);
59
86
  hasMore = response.pagination.next_page !== null;
60
87
  currentPage = response.pagination.next_page || currentPage + 1;
88
+ // Safety check to prevent infinite loops
89
+ if (currentPage > 1000) {
90
+ console.warn('Content Streamline: Stopping pagination at page 1000 to prevent infinite loop');
91
+ break;
92
+ }
61
93
  }
62
94
  return allPosts;
63
95
  }
@@ -2,7 +2,25 @@
2
2
  * File-based cache for posts
3
3
  * Works in Next.js server environment
4
4
  */
5
- import type { Post, PostDetailResponse, CachedPostIndex } from '../types/index.js';
5
+ import type { Post, PostDetailResponse, CachedPostIndex, CacheMetadata } from '../types/index.js';
6
+ /**
7
+ * Generate a hash of the current API configuration
8
+ * Used to detect when env vars change
9
+ */
10
+ export declare function getEnvConfigHash(): string;
11
+ /**
12
+ * Check if API is currently configured
13
+ */
14
+ export declare function isAPIConfigured(): boolean;
15
+ /**
16
+ * Create cache metadata for current state
17
+ */
18
+ export declare function createCacheMetadata(apiCallSucceeded: boolean): CacheMetadata;
19
+ /**
20
+ * Validate if cached data should be used
21
+ * Returns false if cache was created in an invalid state
22
+ */
23
+ export declare function shouldUseCachedData(metadata: CacheMetadata | undefined, maxAgeMinutes: number): boolean;
6
24
  /**
7
25
  * Initialize cache directory
8
26
  */
@@ -20,15 +38,21 @@ export declare function getCachedPost(id: number, language?: string): Promise<Po
20
38
  */
21
39
  export declare function getAllCachedPosts(): Promise<Post[]>;
22
40
  /**
23
- * Update the posts index
41
+ * Update the posts index with metadata
24
42
  */
25
- export declare function updatePostsIndex(posts: Post[]): Promise<void>;
43
+ export declare function updatePostsIndex(posts: Post[], apiCallSucceeded?: boolean): Promise<void>;
26
44
  /**
27
45
  * Get the posts index
28
46
  */
29
47
  export declare function getPostsIndex(): Promise<CachedPostIndex | null>;
30
48
  /**
31
- * Check if cache needs refresh (older than specified minutes)
49
+ * Check if cache needs refresh
50
+ * Returns true if:
51
+ * - No cache exists
52
+ * - Cache is older than maxAgeMinutes
53
+ * - Cache was created when API was not configured (but is now)
54
+ * - Cache was created from a failed API call
55
+ * - API configuration has changed
32
56
  */
33
57
  export declare function shouldRefreshCache(maxAgeMinutes?: number): Promise<boolean>;
34
58
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"file-cache.d.ts","sourceRoot":"","sources":["../../src/cache/file-cache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAMnF;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAO/C;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAa,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAS3G;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CA0BzD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBnE;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAOrE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,aAAa,GAAE,MAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CASrF;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAYhD"}
1
+ {"version":3,"file":"file-cache.d.ts","sourceRoot":"","sources":["../../src/cache/file-cache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAMlG;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAIzC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAIzC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,OAAO,GAAG,aAAa,CAO5E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CA8BvG;AAED;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAO/C;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAa,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAS3G;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CA0BzD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,gBAAgB,GAAE,OAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBrG;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAOrE;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,aAAa,GAAE,MAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAqBrF;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAYhD"}
@@ -4,9 +4,68 @@
4
4
  */
5
5
  import { writeFile, readFile, mkdir, readdir, unlink } from 'fs/promises';
6
6
  import { join } from 'path';
7
+ import { createHash } from 'crypto';
7
8
  const CACHE_DIR = join(process.cwd(), '.next', 'content-streamline-cache');
8
9
  const POSTS_INDEX_FILE = join(CACHE_DIR, 'posts-index.json');
9
10
  const POSTS_DIR = join(CACHE_DIR, 'posts');
11
+ /**
12
+ * Generate a hash of the current API configuration
13
+ * Used to detect when env vars change
14
+ */
15
+ export function getEnvConfigHash() {
16
+ const baseUrl = process.env.CONTENT_STREAMLINE_API_BASE_URL || process.env.API_BASE_URL || '';
17
+ const accessToken = process.env.CONTENT_STREAMLINE_API_ACCESS_TOKEN || process.env.API_ACCESS_TOKEN || '';
18
+ return createHash('md5').update(`${baseUrl}:${accessToken}`).digest('hex').substring(0, 16);
19
+ }
20
+ /**
21
+ * Check if API is currently configured
22
+ */
23
+ export function isAPIConfigured() {
24
+ const baseUrl = process.env.CONTENT_STREAMLINE_API_BASE_URL || process.env.API_BASE_URL;
25
+ const accessToken = process.env.CONTENT_STREAMLINE_API_ACCESS_TOKEN || process.env.API_ACCESS_TOKEN;
26
+ return Boolean(baseUrl && accessToken);
27
+ }
28
+ /**
29
+ * Create cache metadata for current state
30
+ */
31
+ export function createCacheMetadata(apiCallSucceeded) {
32
+ return {
33
+ timestamp: Date.now(),
34
+ apiConfigured: isAPIConfigured(),
35
+ apiCallSucceeded,
36
+ envConfigHash: getEnvConfigHash(),
37
+ };
38
+ }
39
+ /**
40
+ * Validate if cached data should be used
41
+ * Returns false if cache was created in an invalid state
42
+ */
43
+ export function shouldUseCachedData(metadata, maxAgeMinutes) {
44
+ // No metadata means old cache format - don't trust it
45
+ if (!metadata) {
46
+ return false;
47
+ }
48
+ // Don't use cache if it was created when API wasn't configured
49
+ // but API is now configured (user added env vars)
50
+ if (!metadata.apiConfigured && isAPIConfigured()) {
51
+ return false;
52
+ }
53
+ // Don't use cache if API call failed when it was created
54
+ if (!metadata.apiCallSucceeded) {
55
+ return false;
56
+ }
57
+ // Don't use cache if env config changed (different API credentials)
58
+ const currentHash = getEnvConfigHash();
59
+ if (metadata.envConfigHash && metadata.envConfigHash !== currentHash) {
60
+ return false;
61
+ }
62
+ // Check cache age
63
+ const ageMinutes = (Date.now() - metadata.timestamp) / (1000 * 60);
64
+ if (ageMinutes > maxAgeMinutes) {
65
+ return false;
66
+ }
67
+ return true;
68
+ }
10
69
  /**
11
70
  * Initialize cache directory
12
71
  */
@@ -71,9 +130,9 @@ export async function getAllCachedPosts() {
71
130
  }
72
131
  }
73
132
  /**
74
- * Update the posts index
133
+ * Update the posts index with metadata
75
134
  */
76
- export async function updatePostsIndex(posts) {
135
+ export async function updatePostsIndex(posts, apiCallSucceeded = true) {
77
136
  await initCache();
78
137
  const index = {
79
138
  posts: posts.flatMap(post => post.post_translations.map(translation => ({
@@ -83,6 +142,7 @@ export async function updatePostsIndex(posts) {
83
142
  updated_at: post.created_at,
84
143
  }))),
85
144
  last_sync: new Date().toISOString(),
145
+ metadata: createCacheMetadata(apiCallSucceeded),
86
146
  };
87
147
  await writeFile(POSTS_INDEX_FILE, JSON.stringify(index, null, 2), 'utf-8');
88
148
  }
@@ -99,12 +159,28 @@ export async function getPostsIndex() {
99
159
  }
100
160
  }
101
161
  /**
102
- * Check if cache needs refresh (older than specified minutes)
162
+ * Check if cache needs refresh
163
+ * Returns true if:
164
+ * - No cache exists
165
+ * - Cache is older than maxAgeMinutes
166
+ * - Cache was created when API was not configured (but is now)
167
+ * - Cache was created from a failed API call
168
+ * - API configuration has changed
103
169
  */
104
170
  export async function shouldRefreshCache(maxAgeMinutes = 60) {
105
171
  const index = await getPostsIndex();
106
172
  if (!index)
107
173
  return true;
174
+ // Use new metadata-based validation if available
175
+ if (index.metadata) {
176
+ return !shouldUseCachedData(index.metadata, maxAgeMinutes);
177
+ }
178
+ // Fallback for old cache format without metadata
179
+ // If API is now configured, refresh to get proper metadata
180
+ if (isAPIConfigured()) {
181
+ return true;
182
+ }
183
+ // Legacy age check for old cache format
108
184
  const lastSync = new Date(index.last_sync);
109
185
  const now = new Date();
110
186
  const ageMinutes = (now.getTime() - lastSync.getTime()) / (1000 * 60);
@@ -3,107 +3,266 @@
3
3
  * You can override these with your own CSS
4
4
  */
5
5
 
6
- /* Posts List */
7
- .content-streamline-posts-list {
6
+ /* ==========================================================================
7
+ Latest Posts (Featured/Hero Section)
8
+ ========================================================================== */
9
+
10
+ .content-streamline-latest-posts {
8
11
  display: grid;
9
- grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
10
- gap: 2rem;
12
+ grid-template-columns: repeat(3, 1fr);
13
+ gap: 1.5rem;
11
14
  margin: 2rem 0;
12
15
  }
13
16
 
14
- .content-streamline-post-card {
17
+ /* First card spans full width on larger screens */
18
+ .content-streamline-latest-posts:has(.content-streamline-latest-card--featured) {
19
+ grid-template-columns: 1fr;
20
+ }
21
+
22
+ .content-streamline-latest-posts:has(.content-streamline-latest-card--featured) .content-streamline-latest-card--featured {
23
+ display: grid;
24
+ grid-template-columns: 1.2fr 1fr;
25
+ gap: 2rem;
26
+ }
27
+
28
+ .content-streamline-latest-posts:has(.content-streamline-latest-card--featured) .content-streamline-latest-card:not(.content-streamline-latest-card--featured) {
29
+ display: none;
30
+ }
31
+
32
+ /* When there are multiple cards, show grid */
33
+ .content-streamline-latest-posts:has(.content-streamline-latest-card:nth-child(2)) {
34
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
35
+ }
36
+
37
+ .content-streamline-latest-posts:has(.content-streamline-latest-card:nth-child(2)) .content-streamline-latest-card--featured {
38
+ grid-column: 1 / -1;
39
+ display: grid;
40
+ grid-template-columns: 1.5fr 1fr;
41
+ gap: 2.5rem;
42
+ }
43
+
44
+ .content-streamline-latest-posts:has(.content-streamline-latest-card:nth-child(2)) .content-streamline-latest-card:not(.content-streamline-latest-card--featured) {
45
+ display: flex;
46
+ flex-direction: column;
47
+ }
48
+
49
+ .content-streamline-latest-card {
15
50
  background: #ffffff;
16
- border-radius: 12px;
51
+ border-radius: 16px;
17
52
  overflow: hidden;
18
53
  border: 1px solid #e5e7eb;
19
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
20
- transition: transform 0.2s, box-shadow 0.2s;
21
- display: flex;
22
- flex-direction: column;
54
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
55
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
23
56
  }
24
57
 
25
- .content-streamline-post-card:hover {
58
+ .content-streamline-latest-card:hover {
26
59
  transform: translateY(-4px);
27
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
60
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.1);
28
61
  }
29
62
 
30
- .content-streamline-post-image-link {
63
+ .content-streamline-latest-image-link {
31
64
  display: block;
32
65
  text-decoration: none;
33
- width: 100%;
66
+ overflow: hidden;
34
67
  }
35
68
 
36
- .content-streamline-post-image {
69
+ .content-streamline-latest-card--featured .content-streamline-latest-image-link {
70
+ border-radius: 16px 0 0 16px;
71
+ }
72
+
73
+ .content-streamline-latest-image {
37
74
  width: 100%;
38
75
  aspect-ratio: 16 / 10;
39
76
  overflow: hidden;
40
- background: #f3f4f6;
77
+ background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
78
+ }
79
+
80
+ .content-streamline-latest-card--featured .content-streamline-latest-image {
81
+ aspect-ratio: 16 / 11;
82
+ height: 100%;
41
83
  }
42
84
 
43
- .content-streamline-post-image img {
85
+ .content-streamline-latest-image img {
44
86
  width: 100%;
45
87
  height: 100%;
46
88
  object-fit: cover;
47
- transition: transform 0.3s;
89
+ transition: transform 0.4s ease;
48
90
  }
49
91
 
50
- .content-streamline-post-card:hover .content-streamline-post-image img {
92
+ .content-streamline-latest-card:hover .content-streamline-latest-image img {
51
93
  transform: scale(1.05);
52
94
  }
53
95
 
54
- .content-streamline-post-content {
96
+ .content-streamline-latest-content {
55
97
  padding: 1.5rem;
56
- flex: 1;
57
98
  display: flex;
58
99
  flex-direction: column;
100
+ justify-content: center;
59
101
  }
60
102
 
61
- .content-streamline-post-date {
62
- font-size: 0.875rem;
103
+ .content-streamline-latest-card--featured .content-streamline-latest-content {
104
+ padding: 2rem 2rem 2rem 0;
105
+ }
106
+
107
+ .content-streamline-latest-date {
108
+ font-size: 0.8125rem;
63
109
  color: #6b7280;
64
110
  margin-bottom: 0.75rem;
65
111
  text-transform: uppercase;
66
- letter-spacing: 0.05em;
112
+ letter-spacing: 0.08em;
113
+ font-weight: 500;
67
114
  }
68
115
 
69
- .content-streamline-post-title {
70
- font-size: 1.5rem;
71
- font-weight: 600;
72
- margin: 0 0 1rem 0;
73
- line-height: 1.3;
116
+ .content-streamline-latest-title {
117
+ font-size: 1.25rem;
118
+ font-weight: 700;
119
+ margin: 0 0 0.75rem 0;
120
+ line-height: 1.35;
74
121
  }
75
122
 
76
- .content-streamline-post-title a {
123
+ .content-streamline-latest-card--featured .content-streamline-latest-title {
124
+ font-size: 1.75rem;
125
+ margin-bottom: 1rem;
126
+ }
127
+
128
+ .content-streamline-latest-title a {
77
129
  color: #111827;
78
130
  text-decoration: none;
79
- transition: color 0.2s;
131
+ transition: color 0.2s ease;
80
132
  }
81
133
 
82
- .content-streamline-post-title a:hover {
134
+ .content-streamline-latest-title a:hover {
83
135
  color: #3b82f6;
84
136
  }
85
137
 
86
- .content-streamline-post-excerpt {
138
+ .content-streamline-latest-excerpt {
87
139
  color: #6b7280;
88
140
  line-height: 1.6;
89
141
  margin: 0 0 1rem 0;
90
- flex: 1;
142
+ font-size: 0.9375rem;
143
+ display: -webkit-box;
144
+ -webkit-line-clamp: 3;
145
+ -webkit-box-orient: vertical;
146
+ overflow: hidden;
147
+ }
148
+
149
+ .content-streamline-latest-card--featured .content-streamline-latest-excerpt {
150
+ font-size: 1rem;
151
+ -webkit-line-clamp: 4;
91
152
  }
92
153
 
93
- .content-streamline-post-link {
154
+ .content-streamline-latest-link {
94
155
  color: #3b82f6;
95
156
  text-decoration: none;
96
- font-weight: 500;
157
+ font-weight: 600;
158
+ font-size: 0.9375rem;
159
+ transition: color 0.2s ease;
97
160
  margin-top: auto;
98
- transition: color 0.2s;
99
161
  }
100
162
 
101
- .content-streamline-post-link:hover {
163
+ .content-streamline-latest-link:hover {
102
164
  color: #2563eb;
103
- text-decoration: underline;
104
165
  }
105
166
 
106
- /* Post Detail */
167
+ /* ==========================================================================
168
+ Posts List (Vertical List with Image on Left)
169
+ ========================================================================== */
170
+
171
+ .content-streamline-list {
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: 1.25rem;
175
+ margin: 2rem 0;
176
+ }
177
+
178
+ .content-streamline-list-item {
179
+ display: grid;
180
+ grid-template-columns: 180px 1fr;
181
+ gap: 1.25rem;
182
+ padding: 1rem;
183
+ background: #ffffff;
184
+ border-radius: 12px;
185
+ border: 1px solid #e5e7eb;
186
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
187
+ }
188
+
189
+ .content-streamline-list-item:hover {
190
+ border-color: #d1d5db;
191
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
192
+ }
193
+
194
+ .content-streamline-list-image-link {
195
+ display: block;
196
+ text-decoration: none;
197
+ border-radius: 8px;
198
+ overflow: hidden;
199
+ }
200
+
201
+ .content-streamline-list-image {
202
+ width: 100%;
203
+ aspect-ratio: 16 / 11;
204
+ overflow: hidden;
205
+ background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
206
+ border-radius: 8px;
207
+ }
208
+
209
+ .content-streamline-list-image img {
210
+ width: 100%;
211
+ height: 100%;
212
+ object-fit: cover;
213
+ transition: transform 0.3s ease;
214
+ }
215
+
216
+ .content-streamline-list-item:hover .content-streamline-list-image img {
217
+ transform: scale(1.05);
218
+ }
219
+
220
+ .content-streamline-list-content {
221
+ display: flex;
222
+ flex-direction: column;
223
+ justify-content: center;
224
+ padding: 0.25rem 0;
225
+ }
226
+
227
+ .content-streamline-list-date {
228
+ font-size: 0.75rem;
229
+ color: #9ca3af;
230
+ margin-bottom: 0.375rem;
231
+ font-weight: 500;
232
+ }
233
+
234
+ .content-streamline-list-title {
235
+ font-size: 1.0625rem;
236
+ font-weight: 600;
237
+ margin: 0 0 0.5rem 0;
238
+ line-height: 1.4;
239
+ }
240
+
241
+ .content-streamline-list-title a {
242
+ color: #111827;
243
+ text-decoration: none;
244
+ transition: color 0.2s ease;
245
+ }
246
+
247
+ .content-streamline-list-title a:hover {
248
+ color: #3b82f6;
249
+ }
250
+
251
+ .content-streamline-list-excerpt {
252
+ color: #6b7280;
253
+ line-height: 1.5;
254
+ margin: 0;
255
+ font-size: 0.875rem;
256
+ display: -webkit-box;
257
+ -webkit-line-clamp: 2;
258
+ -webkit-box-orient: vertical;
259
+ overflow: hidden;
260
+ }
261
+
262
+ /* ==========================================================================
263
+ Post Detail
264
+ ========================================================================== */
265
+
107
266
  .content-streamline-post-detail {
108
267
  max-width: 800px;
109
268
  margin: 0 auto;
@@ -298,6 +457,10 @@
298
457
  text-align: center;
299
458
  }
300
459
 
460
+ /* ==========================================================================
461
+ Empty States
462
+ ========================================================================== */
463
+
301
464
  .content-streamline-empty,
302
465
  .content-streamline-post-not-found {
303
466
  text-align: center;
@@ -305,13 +468,59 @@
305
468
  color: #6b7280;
306
469
  }
307
470
 
308
- /* Responsive */
471
+ /* ==========================================================================
472
+ Responsive
473
+ ========================================================================== */
474
+
475
+ @media (max-width: 1024px) {
476
+ .content-streamline-latest-posts:has(.content-streamline-latest-card:nth-child(2)) .content-streamline-latest-card--featured {
477
+ grid-template-columns: 1fr 1fr;
478
+ gap: 1.5rem;
479
+ }
480
+ }
481
+
309
482
  @media (max-width: 768px) {
310
- .content-streamline-posts-list {
483
+ /* Latest Posts */
484
+ .content-streamline-latest-posts {
311
485
  grid-template-columns: 1fr;
312
- gap: 1.5rem;
486
+ gap: 1.25rem;
487
+ }
488
+
489
+ .content-streamline-latest-posts:has(.content-streamline-latest-card--featured) .content-streamline-latest-card--featured,
490
+ .content-streamline-latest-posts:has(.content-streamline-latest-card:nth-child(2)) .content-streamline-latest-card--featured {
491
+ grid-template-columns: 1fr;
492
+ gap: 0;
313
493
  }
314
494
 
495
+ .content-streamline-latest-card--featured .content-streamline-latest-image-link {
496
+ border-radius: 16px 16px 0 0;
497
+ }
498
+
499
+ .content-streamline-latest-card--featured .content-streamline-latest-content {
500
+ padding: 1.5rem;
501
+ }
502
+
503
+ .content-streamline-latest-card--featured .content-streamline-latest-title {
504
+ font-size: 1.375rem;
505
+ }
506
+
507
+ /* Posts List */
508
+ .content-streamline-list-item {
509
+ grid-template-columns: 120px 1fr;
510
+ gap: 1rem;
511
+ padding: 0.75rem;
512
+ }
513
+
514
+ .content-streamline-list-title {
515
+ font-size: 0.9375rem;
516
+ }
517
+
518
+ .content-streamline-list-excerpt {
519
+ font-size: 0.8125rem;
520
+ -webkit-line-clamp: 2;
521
+ }
522
+
523
+ /* Post Detail */
315
524
  .content-streamline-post-detail {
316
525
  padding: 1.5rem 1rem;
317
526
  }
@@ -329,3 +538,14 @@
329
538
  }
330
539
  }
331
540
 
541
+ @media (max-width: 480px) {
542
+ /* Posts List - stack vertically on very small screens */
543
+ .content-streamline-list-item {
544
+ grid-template-columns: 1fr;
545
+ gap: 0.75rem;
546
+ }
547
+
548
+ .content-streamline-list-image {
549
+ aspect-ratio: 16 / 9;
550
+ }
551
+ }
package/dist/index.d.ts CHANGED
@@ -2,8 +2,9 @@
2
2
  * Content Streamline Next.js Library
3
3
  * Main entry point
4
4
  */
5
- export type { Post, PostDetailResponse, PostTranslation, PostImage, PostsResponse, Pagination, } from './types/index.js';
5
+ export type { Post, PostDetailResponse, PostTranslation, PostImage, PostsResponse, Pagination, CacheMetadata, } from './types/index.js';
6
6
  export { getAllPosts, getPost, getPostBySlug, } from './server/index.js';
7
+ export { clearCache, isAPIConfigured, } from './cache/file-cache.js';
7
8
  export { PostsList, PostDetail, LatestPosts, } from './components/index.js';
8
9
  export type { PostsListProps, PostDetailProps, LatestPostsProps, } from './components/index.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EACV,IAAI,EACJ,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,aAAa,EACb,UAAU,GACX,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,WAAW,EACX,OAAO,EACP,aAAa,GACd,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,SAAS,EACT,UAAU,EACV,WAAW,GACZ,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,GACjB,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EACV,IAAI,EACJ,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,aAAa,EACb,UAAU,EACV,aAAa,GACd,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,WAAW,EACX,OAAO,EACP,aAAa,GACd,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,UAAU,EACV,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,SAAS,EACT,UAAU,EACV,WAAW,GACZ,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,GACjB,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -4,5 +4,7 @@
4
4
  */
5
5
  // Export server functions
6
6
  export { getAllPosts, getPost, getPostBySlug, } from './server/index.js';
7
+ // Export cache utilities
8
+ export { clearCache, isAPIConfigured, } from './cache/file-cache.js';
7
9
  // Export components
8
10
  export { PostsList, PostDetail, LatestPosts, } from './components/index.js';
@@ -6,6 +6,10 @@ import type { Post, PostDetailResponse } from '../types/index.js';
6
6
  /**
7
7
  * Get all posts (with automatic cache refresh)
8
8
  * Use this in Server Components or API Routes
9
+ *
10
+ * Note: Only successful API responses are cached. Failed API calls
11
+ * (network errors, auth failures, etc.) will NOT be cached, allowing
12
+ * subsequent calls to retry the API.
9
13
  */
10
14
  export declare function getAllPosts(options?: {
11
15
  maxCacheAge?: number;
@@ -15,6 +19,9 @@ export declare function getAllPosts(options?: {
15
19
  /**
16
20
  * Get a single post by ID
17
21
  * Use this in Server Components or API Routes
22
+ *
23
+ * Note: Only successful API responses are cached. Failed API calls
24
+ * will NOT be cached, allowing subsequent calls to retry the API.
18
25
  */
19
26
  export declare function getPost(id: number, options?: {
20
27
  language?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAkBlE;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CA2ClB;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,GACA,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAiCpC;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA2BpC;AAGD,YAAY,EACV,IAAI,EACJ,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,aAAa,EACb,UAAU,GACX,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AA+BlE;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAkGlB;AAED;;;;;;GAMG;AACH,wBAAsB,OAAO,CAC3B,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,GACA,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAoDpC;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA2BpC;AAGD,YAAY,EACV,IAAI,EACJ,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,aAAa,EACb,UAAU,GACX,MAAM,mBAAmB,CAAC"}
@@ -6,22 +6,40 @@ import { createAPIClient } from '../api/client.js';
6
6
  import { getAllCachedPosts, getCachedPost, cachePost, updatePostsIndex, shouldRefreshCache, } from '../cache/file-cache.js';
7
7
  /**
8
8
  * Get API configuration from environment variables
9
+ * Returns null if not configured (instead of throwing)
9
10
  */
10
11
  function getAPIConfig() {
11
12
  const baseUrl = process.env.CONTENT_STREAMLINE_API_BASE_URL || process.env.API_BASE_URL;
12
13
  const accessToken = process.env.CONTENT_STREAMLINE_API_ACCESS_TOKEN || process.env.API_ACCESS_TOKEN;
13
14
  if (!baseUrl || !accessToken) {
14
- throw new Error('Missing API configuration. Set CONTENT_STREAMLINE_API_BASE_URL and CONTENT_STREAMLINE_API_ACCESS_TOKEN environment variables.');
15
+ return null;
15
16
  }
16
17
  return { baseUrl, accessToken };
17
18
  }
19
+ /**
20
+ * Get API configuration, throwing if not configured
21
+ * Use this when API is required
22
+ */
23
+ function requireAPIConfig() {
24
+ const config = getAPIConfig();
25
+ if (!config) {
26
+ throw new Error('Missing API configuration. Set CONTENT_STREAMLINE_API_BASE_URL and CONTENT_STREAMLINE_API_ACCESS_TOKEN environment variables.');
27
+ }
28
+ return config;
29
+ }
18
30
  /**
19
31
  * Get all posts (with automatic cache refresh)
20
32
  * Use this in Server Components or API Routes
33
+ *
34
+ * Note: Only successful API responses are cached. Failed API calls
35
+ * (network errors, auth failures, etc.) will NOT be cached, allowing
36
+ * subsequent calls to retry the API.
21
37
  */
22
38
  export async function getAllPosts(options) {
23
39
  const { maxCacheAge = 15, forceRefresh = false, platform } = options || {};
24
- // Check cache freshness
40
+ // Check if API is configured
41
+ const apiConfig = getAPIConfig();
42
+ // Check cache freshness (this also validates cache metadata)
25
43
  if (!forceRefresh) {
26
44
  const needsRefresh = await shouldRefreshCache(maxCacheAge);
27
45
  if (!needsRefresh) {
@@ -40,31 +58,80 @@ export async function getAllPosts(options) {
40
58
  }
41
59
  }
42
60
  }
61
+ // If API is not configured, return empty array but DON'T cache it
62
+ if (!apiConfig) {
63
+ console.warn('Content Streamline: API not configured. Set CONTENT_STREAMLINE_API_BASE_URL and CONTENT_STREAMLINE_API_ACCESS_TOKEN environment variables.');
64
+ return [];
65
+ }
43
66
  // Fetch from API
44
- const { baseUrl, accessToken } = getAPIConfig();
45
- const api = createAPIClient(baseUrl, accessToken);
46
- const posts = await api.getAllPosts(platform);
47
- // Cache all posts
67
+ let posts;
68
+ try {
69
+ const api = createAPIClient(apiConfig.baseUrl, apiConfig.accessToken);
70
+ console.log(`Content Streamline: Fetching posts from API (forceRefresh: ${forceRefresh}, platform: ${platform || 'all'})`);
71
+ posts = await api.getAllPosts(platform);
72
+ console.log(`Content Streamline: Successfully fetched ${posts.length} posts from API`);
73
+ }
74
+ catch (error) {
75
+ // API call failed - DON'T cache the error, just return empty
76
+ // This allows subsequent calls to retry the API
77
+ const errorMessage = error instanceof Error ? error.message : String(error);
78
+ console.error('Content Streamline: Failed to fetch posts from API:', errorMessage);
79
+ if (error instanceof Error && error.stack) {
80
+ console.error('Content Streamline: Error stack:', error.stack);
81
+ }
82
+ // Try to return stale cache if available (better than nothing)
83
+ const staleCached = await getAllCachedPosts();
84
+ if (staleCached.length > 0) {
85
+ console.warn(`Content Streamline: Returning ${staleCached.length} stale cached posts due to API error`);
86
+ if (platform) {
87
+ const filtered = staleCached.filter(post => post.platform.toLowerCase() === platform.toLowerCase());
88
+ return filtered;
89
+ }
90
+ return staleCached;
91
+ }
92
+ console.warn('Content Streamline: No cached data available, returning empty array');
93
+ return [];
94
+ }
95
+ // Validate that we got posts
96
+ if (!Array.isArray(posts)) {
97
+ console.error('Content Streamline: API returned invalid response (not an array):', typeof posts);
98
+ return [];
99
+ }
100
+ // API call succeeded - cache the results with success metadata
101
+ // Note: We cache individual post details, but failures here don't prevent returning the posts
102
+ let cachedCount = 0;
48
103
  for (const post of posts) {
49
104
  try {
105
+ const api = createAPIClient(apiConfig.baseUrl, apiConfig.accessToken);
50
106
  const fullPost = await api.getPost(post.id, 'markdown');
51
107
  await cachePost(fullPost);
108
+ cachedCount++;
52
109
  }
53
110
  catch (error) {
54
- console.error(`Failed to cache post ${post.id}:`, error);
111
+ // Log but don't fail - we still want to return the posts
112
+ console.warn(`Content Streamline: Failed to cache full details for post ${post.id}:`, error instanceof Error ? error.message : String(error));
55
113
  }
56
114
  }
57
- // Update index
58
- await updatePostsIndex(posts);
115
+ if (cachedCount > 0) {
116
+ console.log(`Content Streamline: Cached ${cachedCount} of ${posts.length} posts`);
117
+ }
118
+ // Update index with success metadata
119
+ await updatePostsIndex(posts, true);
120
+ console.log(`Content Streamline: Returning ${posts.length} posts`);
59
121
  return posts;
60
122
  }
61
123
  /**
62
124
  * Get a single post by ID
63
125
  * Use this in Server Components or API Routes
126
+ *
127
+ * Note: Only successful API responses are cached. Failed API calls
128
+ * will NOT be cached, allowing subsequent calls to retry the API.
64
129
  */
65
130
  export async function getPost(id, options) {
66
131
  const { language = 'en', contentFormat = 'markdown', maxCacheAge = 15, forceRefresh = false, } = options || {};
67
- // Try cache first
132
+ // Check if API is configured
133
+ const apiConfig = getAPIConfig();
134
+ // Try cache first (cache validation includes metadata checks)
68
135
  if (!forceRefresh) {
69
136
  const needsRefresh = await shouldRefreshCache(maxCacheAge);
70
137
  if (!needsRefresh) {
@@ -74,17 +141,28 @@ export async function getPost(id, options) {
74
141
  }
75
142
  }
76
143
  }
144
+ // If API is not configured, return null but DON'T cache it
145
+ if (!apiConfig) {
146
+ console.warn('Content Streamline: API not configured. Set CONTENT_STREAMLINE_API_BASE_URL and CONTENT_STREAMLINE_API_ACCESS_TOKEN environment variables.');
147
+ return null;
148
+ }
77
149
  // Fetch from API
78
150
  try {
79
- const { baseUrl, accessToken } = getAPIConfig();
80
- const api = createAPIClient(baseUrl, accessToken);
151
+ const api = createAPIClient(apiConfig.baseUrl, apiConfig.accessToken);
81
152
  const post = await api.getPost(id, contentFormat);
82
- // Cache it
153
+ // API call succeeded - cache it
83
154
  await cachePost(post);
84
155
  return post;
85
156
  }
86
157
  catch (error) {
87
- console.error(`Failed to fetch post ${id}:`, error);
158
+ // API call failed - DON'T cache the error
159
+ // Try to return stale cache if available
160
+ console.error(`Content Streamline: Failed to fetch post ${id}:`, error);
161
+ const staleCached = await getCachedPost(id, language);
162
+ if (staleCached) {
163
+ console.warn(`Content Streamline: Returning stale cached data for post ${id} due to API error`);
164
+ return staleCached;
165
+ }
88
166
  return null;
89
167
  }
90
168
  }
@@ -39,6 +39,15 @@ export interface PostsResponse {
39
39
  export interface PostDetailResponse extends Post {
40
40
  post_translations: PostTranslation[];
41
41
  }
42
+ /**
43
+ * Metadata stored with cache entries to track API state
44
+ */
45
+ export interface CacheMetadata {
46
+ timestamp: number;
47
+ apiConfigured: boolean;
48
+ apiCallSucceeded: boolean;
49
+ envConfigHash?: string;
50
+ }
42
51
  export interface CachedPostIndex {
43
52
  posts: Array<{
44
53
  id: number;
@@ -47,5 +56,6 @@ export interface CachedPostIndex {
47
56
  updated_at: string;
48
57
  }>;
49
58
  last_sync: string;
59
+ metadata?: CacheMetadata;
50
60
  }
51
61
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,eAAe,EAAE,CAAC;IACrC,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,UAAU,CAAC;IACvB,IAAI,EAAE,IAAI,EAAE,CAAC;CACd;AAED,MAAM,WAAW,kBAAmB,SAAQ,IAAI;IAC9C,iBAAiB,EAAE,eAAe,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,KAAK,CAAC;QACX,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,SAAS,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,eAAe,EAAE,CAAC;IACrC,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,UAAU,CAAC;IACvB,IAAI,EAAE,IAAI,EAAE,CAAC;CACd;AAED,MAAM,WAAW,kBAAmB,SAAQ,IAAI;IAC9C,iBAAiB,EAAE,eAAe,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,KAAK,CAAC;QACX,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@content-streamline/nextjs",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Next.js library for Content Streamline API with reusable components",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",