ayezee-astro-cms 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.
package/README.md ADDED
@@ -0,0 +1,240 @@
1
+ # @ayezee/astro-cms
2
+
3
+ AyeZee CMS integration for Astro with automatic data fetching, form handling, and validation.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Automatic Data Fetching** - Fetches CMS data during build time
8
+ - 📦 **Type-Safe** - Full TypeScript support with proper types
9
+ - 🔄 **Build-Time Caching** - No runtime API calls needed
10
+ - ✅ **Form Validation** - Client-side and server-side validation support
11
+ - 🔒 **Turnstile Integration** - Built-in Cloudflare Turnstile support
12
+ - 🎨 **Zero Config** - Works with environment variables
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @ayezee/astro-cms
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ### 1. Add Environment Variables
23
+
24
+ Create a `.env` file in your project root:
25
+
26
+ ```env
27
+ PUBLIC_CMS_DOMAIN=http://localhost:3000
28
+ PUBLIC_PROJECT_SLUG=your-project-slug
29
+ PUBLIC_AYEZEE_API_KEY=AZ_your_api_key_here
30
+ ```
31
+
32
+ ### 2. Add Integration to Astro Config
33
+
34
+ ```js
35
+ // astro.config.mjs
36
+ import { defineConfig } from 'astro/config';
37
+ import { ayezeeCms } from '@ayezee/astro-cms/integration';
38
+
39
+ export default defineConfig({
40
+ integrations: [ayezeeCms()],
41
+ });
42
+ ```
43
+
44
+ ### 3. Use CMS Data in Your Pages
45
+
46
+ ```astro
47
+ ---
48
+ // src/pages/index.astro
49
+ import { initCmsHelper, getModuleData } from '@ayezee/astro-cms';
50
+ import cmsData from '../data/cms-cache.json';
51
+
52
+ // Initialize the helper (only needed once)
53
+ initCmsHelper(cmsData);
54
+
55
+ // Get your data
56
+ const testimonials = getModuleData('testimonials');
57
+ ---
58
+
59
+ <div>
60
+ {testimonials.map((item) => (
61
+ <div>
62
+ <h3>{item.data.name}</h3>
63
+ <p>{item.data.message}</p>
64
+ </div>
65
+ ))}
66
+ </div>
67
+ ```
68
+
69
+ ## API Reference
70
+
71
+ ### Integration Options
72
+
73
+ ```ts
74
+ ayezeeCms({
75
+ // CMS domain (defaults to PUBLIC_CMS_DOMAIN env var)
76
+ cmsDomain?: string;
77
+
78
+ // Project slug (defaults to PUBLIC_PROJECT_SLUG env var)
79
+ projectSlug?: string;
80
+
81
+ // Output directory for cache (defaults to 'src/data')
82
+ outputDir?: string;
83
+
84
+ // Cache file name (defaults to 'cms-cache.json')
85
+ cacheFileName?: string;
86
+
87
+ // Skip build if fetch fails (defaults to false)
88
+ skipOnError?: boolean;
89
+ });
90
+ ```
91
+
92
+ ### Helper Functions
93
+
94
+ #### Module Retrieval
95
+
96
+ ```ts
97
+ import {
98
+ getModule,
99
+ getModuleByLabel,
100
+ getModuleBySlug,
101
+ getModules,
102
+ getModulesByCategory,
103
+ getModulesByDataType,
104
+ } from '@ayezee/astro-cms';
105
+
106
+ // Get by instance key
107
+ const module = getModule('contact_form-123');
108
+
109
+ // Get by label (case-insensitive)
110
+ const module = getModuleByLabel('Contact Form');
111
+
112
+ // Get by slug
113
+ const module = getModuleBySlug('contact-form');
114
+
115
+ // Get all modules
116
+ const allModules = getModules();
117
+
118
+ // Get by category
119
+ const formModules = getModulesByCategory('forms');
120
+
121
+ // Get by type
122
+ const collections = getModulesByDataType('collection');
123
+ ```
124
+
125
+ #### Data Retrieval
126
+
127
+ ```ts
128
+ import {
129
+ getModuleData,
130
+ getModuleDataByLabel,
131
+ getModuleDataBySlug,
132
+ } from '@ayezee/astro-cms';
133
+
134
+ // Get data by instance key
135
+ const data = getModuleData('testimonials-123');
136
+
137
+ // Get data by label
138
+ const data = getModuleDataByLabel('Testimonials');
139
+
140
+ // Get data by slug
141
+ const data = getModuleDataBySlug('testimonials');
142
+ ```
143
+
144
+ #### Form Configuration
145
+
146
+ ```ts
147
+ import { getFormConfig, getTurnstileConfig } from '@ayezee/astro-cms';
148
+
149
+ // Get complete form configuration
150
+ const config = getFormConfig('Contact Form');
151
+ // Returns: { module, turnstile, apiUrl, apiKey }
152
+
153
+ // Get just Turnstile config
154
+ const turnstile = getTurnstileConfig('Contact Form');
155
+ // Returns: { enabled: boolean, siteKey: string | null }
156
+ ```
157
+
158
+ #### Project & Cache Info
159
+
160
+ ```ts
161
+ import { getProject, getCacheInfo } from '@ayezee/astro-cms';
162
+
163
+ // Get project details
164
+ const project = getProject();
165
+ // Returns: { id, slug, name, domain }
166
+
167
+ // Get cache metadata
168
+ const info = getCacheInfo();
169
+ // Returns: { fetchedAt, version, moduleCount }
170
+ ```
171
+
172
+ ## TypeScript Support
173
+
174
+ The package exports all necessary types:
175
+
176
+ ```ts
177
+ import type {
178
+ CachedModule,
179
+ ModuleField,
180
+ ModuleDataItem,
181
+ ValidationRules,
182
+ CMSCache,
183
+ } from '@ayezee/astro-cms';
184
+ ```
185
+
186
+ ## Advanced Usage
187
+
188
+ ### Custom Cache Location
189
+
190
+ ```js
191
+ // astro.config.mjs
192
+ export default defineConfig({
193
+ integrations: [
194
+ ayezeeCms({
195
+ outputDir: 'src/custom/location',
196
+ cacheFileName: 'my-cache.json',
197
+ }),
198
+ ],
199
+ });
200
+ ```
201
+
202
+ ### Skip Build on Error
203
+
204
+ Useful for CI/CD when CMS might be temporarily unavailable:
205
+
206
+ ```js
207
+ export default defineConfig({
208
+ integrations: [
209
+ ayezeeCms({
210
+ skipOnError: process.env.NODE_ENV === 'development',
211
+ }),
212
+ ],
213
+ });
214
+ ```
215
+
216
+ ### Runtime Configuration
217
+
218
+ Override environment variables programmatically:
219
+
220
+ ```js
221
+ export default defineConfig({
222
+ integrations: [
223
+ ayezeeCms({
224
+ cmsDomain: 'https://cms.example.com',
225
+ projectSlug: 'my-project',
226
+ }),
227
+ ],
228
+ });
229
+ ```
230
+
231
+ ## How It Works
232
+
233
+ 1. **Build Time**: The integration fetches all CMS data during `astro build` or `astro dev`
234
+ 2. **Caching**: Data is saved to `src/data/cms-cache.json`
235
+ 3. **Runtime**: Helper functions read from the cached file (no API calls!)
236
+ 4. **Type Safety**: Full TypeScript support with generated types
237
+
238
+ ## License
239
+
240
+ MIT © AyeZee Web Designs
@@ -0,0 +1,176 @@
1
+ /**
2
+ * AyeZee CMS Helper - Build-Time Cached Version
3
+ *
4
+ * Provides utilities to access CMS data from the generated cache file
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { getModule, getModuleData } from '@ayezee/astro-cms';
9
+ *
10
+ * const testimonials = getModuleData('testimonials');
11
+ * const contactForm = getModule('contact-form');
12
+ * ```
13
+ */
14
+ export interface ModuleField {
15
+ key: string;
16
+ label: string;
17
+ fieldType: string;
18
+ required?: boolean;
19
+ options?: unknown[];
20
+ validation?: ValidationRules;
21
+ isPreviewField?: boolean;
22
+ placeholder?: string;
23
+ }
24
+ export interface ValidationRules {
25
+ minLength?: number;
26
+ maxLength?: number;
27
+ pattern?: string;
28
+ min?: number;
29
+ max?: number;
30
+ step?: number;
31
+ maxSize?: string;
32
+ allowedFormats?: string[];
33
+ options?: string[];
34
+ schema?: Record<string, unknown>;
35
+ }
36
+ export interface ModuleDataItem {
37
+ id: string;
38
+ data: Record<string, unknown>;
39
+ sortOrder?: number;
40
+ status?: string;
41
+ ipAddress?: string;
42
+ userAgent?: string;
43
+ createdAt: string;
44
+ updatedAt?: string;
45
+ }
46
+ export interface CachedModule {
47
+ id: string;
48
+ instanceKey: string;
49
+ label: string;
50
+ slug: string;
51
+ dataType: 'collection' | 'singleton' | 'submissions';
52
+ category: string;
53
+ description?: string;
54
+ icon?: string;
55
+ fields: ModuleField[];
56
+ isActive: boolean;
57
+ sortOrder: number;
58
+ data: ModuleDataItem[];
59
+ pagination: {
60
+ total: number;
61
+ limit?: number | null;
62
+ offset?: number;
63
+ count: number;
64
+ };
65
+ parameters: Record<string, unknown>;
66
+ createdAt: string;
67
+ updatedAt: string;
68
+ }
69
+ export interface CMSCache {
70
+ project: {
71
+ id: string;
72
+ slug: string;
73
+ name: string;
74
+ domain?: string;
75
+ };
76
+ modules: CachedModule[];
77
+ fetchedAt: string;
78
+ version: string;
79
+ }
80
+ /**
81
+ * Initialize the CMS helper with cache data
82
+ * This should be called once at the start of your app
83
+ */
84
+ export declare function initCmsHelper(cacheData: CMSCache): void;
85
+ /**
86
+ * Get project information
87
+ */
88
+ export declare function getProject(): {
89
+ id: string;
90
+ slug: string;
91
+ name: string;
92
+ domain?: string;
93
+ };
94
+ /**
95
+ * Get all modules
96
+ */
97
+ export declare function getModules(): CachedModule[];
98
+ /**
99
+ * Get a module by its instance key
100
+ */
101
+ export declare function getModule(instanceKey: string): CachedModule | null;
102
+ /**
103
+ * Get a module by its label (case-insensitive)
104
+ */
105
+ export declare function getModuleByLabel(label: string): CachedModule | null;
106
+ /**
107
+ * Get a module by its slug
108
+ */
109
+ export declare function getModuleBySlug(slug: string): CachedModule | null;
110
+ /**
111
+ * Get modules by category
112
+ */
113
+ export declare function getModulesByCategory(category: string): CachedModule[];
114
+ /**
115
+ * Get modules by data type
116
+ */
117
+ export declare function getModulesByDataType(dataType: 'collection' | 'singleton' | 'submissions'): CachedModule[];
118
+ /**
119
+ * Get all form modules (submissions type)
120
+ */
121
+ export declare function getForms(): CachedModule[];
122
+ /**
123
+ * Get all content collections
124
+ */
125
+ export declare function getCollections(): CachedModule[];
126
+ /**
127
+ * Get all singleton content
128
+ */
129
+ export declare function getSingletons(): CachedModule[];
130
+ /**
131
+ * Get data from a module by instance key
132
+ */
133
+ export declare function getModuleData(instanceKey: string): ModuleDataItem[];
134
+ /**
135
+ * Get data from a module by label
136
+ */
137
+ export declare function getModuleDataByLabel(label: string): ModuleDataItem[];
138
+ /**
139
+ * Get data from a module by slug
140
+ */
141
+ export declare function getModuleDataBySlug(slug: string): ModuleDataItem[];
142
+ /**
143
+ * Get Turnstile configuration for a form module
144
+ */
145
+ export declare function getTurnstileConfig(moduleIdentifier: string): {
146
+ enabled: boolean;
147
+ siteKey: string | null;
148
+ };
149
+ /**
150
+ * Check if a form has Turnstile enabled
151
+ */
152
+ export declare function isTurnstileEnabled(moduleIdentifier: string): boolean;
153
+ /**
154
+ * Get form configuration including all settings
155
+ */
156
+ export declare function getFormConfig(moduleIdentifier: string, options?: {
157
+ apiKey?: string;
158
+ cmsDomain?: string;
159
+ projectSlug?: string;
160
+ }): {
161
+ module: CachedModule | null;
162
+ turnstile: {
163
+ enabled: boolean;
164
+ siteKey: string | null;
165
+ };
166
+ apiUrl: string;
167
+ apiKey: string;
168
+ };
169
+ /**
170
+ * Get metadata about when the cache was last updated
171
+ */
172
+ export declare function getCacheInfo(): {
173
+ fetchedAt: string;
174
+ version: string;
175
+ moduleCount: number;
176
+ };
@@ -0,0 +1,190 @@
1
+ /**
2
+ * AyeZee CMS Helper - Build-Time Cached Version
3
+ *
4
+ * Provides utilities to access CMS data from the generated cache file
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { getModule, getModuleData } from '@ayezee/astro-cms';
9
+ *
10
+ * const testimonials = getModuleData('testimonials');
11
+ * const contactForm = getModule('contact-form');
12
+ * ```
13
+ */
14
+ // Import cache data - will be resolved by the consuming project
15
+ let cache = null;
16
+ /**
17
+ * Initialize the CMS helper with cache data
18
+ * This should be called once at the start of your app
19
+ */
20
+ export function initCmsHelper(cacheData) {
21
+ cache = cacheData;
22
+ }
23
+ /**
24
+ * Get the cache instance (throws if not initialized)
25
+ */
26
+ function getCache() {
27
+ if (!cache) {
28
+ throw new Error('CMS Helper not initialized. Call initCmsHelper() first or import cache data directly.');
29
+ }
30
+ return cache;
31
+ }
32
+ /**
33
+ * Get project information
34
+ */
35
+ export function getProject() {
36
+ return getCache().project;
37
+ }
38
+ /**
39
+ * Get all modules
40
+ */
41
+ export function getModules() {
42
+ return getCache().modules;
43
+ }
44
+ /**
45
+ * Get a module by its instance key
46
+ */
47
+ export function getModule(instanceKey) {
48
+ return getCache().modules.find((mod) => mod.instanceKey === instanceKey) || null;
49
+ }
50
+ /**
51
+ * Get a module by its label (case-insensitive)
52
+ */
53
+ export function getModuleByLabel(label) {
54
+ const normalizedLabel = label.toLowerCase();
55
+ return (getCache().modules.find((mod) => mod.label.toLowerCase() === normalizedLabel) ||
56
+ null);
57
+ }
58
+ /**
59
+ * Get a module by its slug
60
+ */
61
+ export function getModuleBySlug(slug) {
62
+ return getCache().modules.find((mod) => mod.slug === slug) || null;
63
+ }
64
+ /**
65
+ * Get modules by category
66
+ */
67
+ export function getModulesByCategory(category) {
68
+ return getCache().modules.filter((mod) => mod.category === category);
69
+ }
70
+ /**
71
+ * Get modules by data type
72
+ */
73
+ export function getModulesByDataType(dataType) {
74
+ return getCache().modules.filter((mod) => mod.dataType === dataType);
75
+ }
76
+ /**
77
+ * Get all form modules (submissions type)
78
+ */
79
+ export function getForms() {
80
+ return getModulesByDataType('submissions');
81
+ }
82
+ /**
83
+ * Get all content collections
84
+ */
85
+ export function getCollections() {
86
+ return getModulesByDataType('collection');
87
+ }
88
+ /**
89
+ * Get all singleton content
90
+ */
91
+ export function getSingletons() {
92
+ return getModulesByDataType('singleton');
93
+ }
94
+ /**
95
+ * Get data from a module by instance key
96
+ */
97
+ export function getModuleData(instanceKey) {
98
+ const foundModule = getModule(instanceKey);
99
+ return foundModule?.data || [];
100
+ }
101
+ /**
102
+ * Get data from a module by label
103
+ */
104
+ export function getModuleDataByLabel(label) {
105
+ const foundModule = getModuleByLabel(label);
106
+ return foundModule?.data || [];
107
+ }
108
+ /**
109
+ * Get data from a module by slug
110
+ */
111
+ export function getModuleDataBySlug(slug) {
112
+ const foundModule = getModuleBySlug(slug);
113
+ return foundModule?.data || [];
114
+ }
115
+ /**
116
+ * Get Turnstile configuration for a form module
117
+ */
118
+ export function getTurnstileConfig(moduleIdentifier) {
119
+ // Try to find module by instance key, label, or slug
120
+ let module = getModule(moduleIdentifier);
121
+ if (!module) {
122
+ module = getModuleByLabel(moduleIdentifier);
123
+ }
124
+ if (!module) {
125
+ module = getModuleBySlug(moduleIdentifier);
126
+ }
127
+ if (!module || !module.parameters?.turnstile) {
128
+ return { enabled: false, siteKey: null };
129
+ }
130
+ const turnstile = module.parameters.turnstile;
131
+ return {
132
+ enabled: turnstile.enabled === true,
133
+ siteKey: turnstile.siteKey || null,
134
+ };
135
+ }
136
+ /**
137
+ * Check if a form has Turnstile enabled
138
+ */
139
+ export function isTurnstileEnabled(moduleIdentifier) {
140
+ const config = getTurnstileConfig(moduleIdentifier);
141
+ return config.enabled && config.siteKey !== null;
142
+ }
143
+ /**
144
+ * Get form configuration including all settings
145
+ */
146
+ export function getFormConfig(moduleIdentifier, options) {
147
+ // Try to find module by instance key, label, or slug
148
+ let module = getModule(moduleIdentifier);
149
+ if (!module) {
150
+ module = getModuleByLabel(moduleIdentifier);
151
+ }
152
+ if (!module) {
153
+ module = getModuleBySlug(moduleIdentifier);
154
+ }
155
+ // Get configuration from options or environment variables
156
+ const cmsDomain = options?.cmsDomain ||
157
+ (typeof import.meta !== 'undefined' && import.meta.env?.PUBLIC_CMS_DOMAIN) ||
158
+ 'http://localhost:3000';
159
+ const projectSlug = options?.projectSlug ||
160
+ (typeof import.meta !== 'undefined' && import.meta.env?.PUBLIC_PROJECT_SLUG) ||
161
+ '';
162
+ const apiKey = options?.apiKey ||
163
+ (typeof import.meta !== 'undefined' && import.meta.env?.PUBLIC_AYEZEE_API_KEY) ||
164
+ '';
165
+ let domain = cmsDomain;
166
+ if (!domain.startsWith('http://') && !domain.startsWith('https://')) {
167
+ const protocol = domain.includes('localhost') ? 'http' : 'https';
168
+ domain = `${protocol}://${domain}`;
169
+ }
170
+ const apiUrl = module
171
+ ? `${domain}/api/v1/projects/${projectSlug}/submit/${module.instanceKey}`
172
+ : '';
173
+ return {
174
+ module,
175
+ turnstile: getTurnstileConfig(moduleIdentifier),
176
+ apiUrl,
177
+ apiKey,
178
+ };
179
+ }
180
+ /**
181
+ * Get metadata about when the cache was last updated
182
+ */
183
+ export function getCacheInfo() {
184
+ return {
185
+ fetchedAt: getCache().fetchedAt,
186
+ version: getCache().version,
187
+ moduleCount: getCache().modules.length,
188
+ };
189
+ }
190
+ // Types are already exported above, no need to re-export
@@ -0,0 +1,10 @@
1
+ /**
2
+ * AyeZee CMS Astro Integration
3
+ *
4
+ * Provides automatic CMS data fetching and helper utilities for Astro projects
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ export * from './cms-helper.js';
9
+ export { ayezeeCms, type AyezeeCmsOptions } from './integration.js';
10
+ export { ayezeeCms as default } from './integration.js';
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * AyeZee CMS Astro Integration
3
+ *
4
+ * Provides automatic CMS data fetching and helper utilities for Astro projects
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ // Export CMS helper functions and types
9
+ export * from './cms-helper.js';
10
+ // Export integration
11
+ export { ayezeeCms } from './integration.js';
12
+ // Default export
13
+ export { ayezeeCms as default } from './integration.js';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * AyeZee CMS Astro Integration
3
+ *
4
+ * Automatically fetches CMS data during Astro build process
5
+ *
6
+ * @example
7
+ * ```js
8
+ * // astro.config.mjs
9
+ * import { ayezeeCms } from '@ayezee/astro-cms/integration';
10
+ *
11
+ * export default defineConfig({
12
+ * integrations: [ayezeeCms()]
13
+ * });
14
+ * ```
15
+ */
16
+ import type { AstroIntegration } from 'astro';
17
+ export interface AyezeeCmsOptions {
18
+ /**
19
+ * CMS domain URL
20
+ * @default process.env.PUBLIC_CMS_DOMAIN
21
+ */
22
+ cmsDomain?: string;
23
+ /**
24
+ * Project slug identifier
25
+ * @default process.env.PUBLIC_PROJECT_SLUG
26
+ */
27
+ projectSlug?: string;
28
+ /**
29
+ * Output directory for cached data
30
+ * @default 'src/data'
31
+ */
32
+ outputDir?: string;
33
+ /**
34
+ * Cache file name
35
+ * @default 'cms-cache.json'
36
+ */
37
+ cacheFileName?: string;
38
+ /**
39
+ * Skip build if fetch fails
40
+ * @default false
41
+ */
42
+ skipOnError?: boolean;
43
+ }
44
+ /**
45
+ * AyeZee CMS Astro Integration
46
+ */
47
+ export declare function ayezeeCms(options?: AyezeeCmsOptions): AstroIntegration;
48
+ export default ayezeeCms;
@@ -0,0 +1,167 @@
1
+ /**
2
+ * AyeZee CMS Astro Integration
3
+ *
4
+ * Automatically fetches CMS data during Astro build process
5
+ *
6
+ * @example
7
+ * ```js
8
+ * // astro.config.mjs
9
+ * import { ayezeeCms } from '@ayezee/astro-cms/integration';
10
+ *
11
+ * export default defineConfig({
12
+ * integrations: [ayezeeCms()]
13
+ * });
14
+ * ```
15
+ */
16
+ import fs from 'fs';
17
+ import path from 'path';
18
+ /**
19
+ * Load environment variables from .env file
20
+ */
21
+ function loadEnvFile() {
22
+ const envPath = path.join(process.cwd(), '.env');
23
+ if (fs.existsSync(envPath)) {
24
+ const envContent = fs.readFileSync(envPath, 'utf-8');
25
+ const lines = envContent.split('\n');
26
+ for (const line of lines) {
27
+ const trimmed = line.trim();
28
+ if (!trimmed || trimmed.startsWith('#'))
29
+ continue;
30
+ const match = trimmed.match(/^([^=]+)=(.*)$/);
31
+ if (match) {
32
+ const key = match[1].trim();
33
+ const value = match[2].trim().replace(/^["']|["']$/g, '');
34
+ if (!process.env[key]) {
35
+ process.env[key] = value;
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ /**
42
+ * Convert text to URL-friendly slug
43
+ */
44
+ function slugify(text) {
45
+ return text
46
+ .toLowerCase()
47
+ .replace(/[^\w\s-]/g, '')
48
+ .replace(/[\s_-]+/g, '-')
49
+ .replace(/^-+|-+$/g, '');
50
+ }
51
+ /**
52
+ * AyeZee CMS Astro Integration
53
+ */
54
+ export function ayezeeCms(options = {}) {
55
+ return {
56
+ name: 'ayezee-cms',
57
+ hooks: {
58
+ 'astro:config:setup': async ({ config, logger }) => {
59
+ logger.info('🚀 AyeZee CMS: Fetching data...');
60
+ // Load environment variables from .env
61
+ loadEnvFile();
62
+ // Get configuration
63
+ const cmsDomain = options.cmsDomain || process.env.PUBLIC_CMS_DOMAIN;
64
+ const projectSlug = options.projectSlug || process.env.PUBLIC_PROJECT_SLUG;
65
+ const outputDir = options.outputDir || 'src/data';
66
+ const cacheFileName = options.cacheFileName || 'cms-cache.json';
67
+ const skipOnError = options.skipOnError || false;
68
+ // Validate config
69
+ if (!cmsDomain || !projectSlug) {
70
+ const errorMsg = 'Missing environment variables:';
71
+ if (!cmsDomain)
72
+ logger.error(` - PUBLIC_CMS_DOMAIN`);
73
+ if (!projectSlug)
74
+ logger.error(` - PUBLIC_PROJECT_SLUG`);
75
+ if (skipOnError) {
76
+ logger.warn('⚠️ Skipping CMS data fetch due to missing config');
77
+ return;
78
+ }
79
+ throw new Error(`AyeZee CMS integration requires PUBLIC_CMS_DOMAIN and PUBLIC_PROJECT_SLUG`);
80
+ }
81
+ logger.info(` Domain: ${cmsDomain}`);
82
+ logger.info(` Project: ${projectSlug}`);
83
+ try {
84
+ // Build API URL
85
+ let domain = cmsDomain;
86
+ if (!domain.startsWith('http://') && !domain.startsWith('https://')) {
87
+ const protocol = domain.includes('localhost') ? 'http' : 'https';
88
+ domain = `${protocol}://${domain}`;
89
+ }
90
+ const baseUrl = `${domain}/api/v1/projects/${projectSlug}`;
91
+ // Fetch modules
92
+ logger.info('📡 Fetching modules...');
93
+ const modulesResponse = await fetch(`${baseUrl}/modules`);
94
+ if (!modulesResponse.ok) {
95
+ throw new Error(`API error: ${modulesResponse.status} ${modulesResponse.statusText}`);
96
+ }
97
+ const modulesResult = await modulesResponse.json();
98
+ if (!modulesResult.success) {
99
+ throw new Error(modulesResult.message || 'Failed to fetch modules');
100
+ }
101
+ const modules = modulesResult.data.modules;
102
+ logger.info(`✅ Found ${modules.length} modules`);
103
+ // Fetch data for each module
104
+ const modulesWithData = [];
105
+ for (const module of modules) {
106
+ try {
107
+ const dataResponse = await fetch(`${baseUrl}/modules/${module.instanceKey}/data`);
108
+ const dataResult = await dataResponse.json();
109
+ const itemCount = dataResult.data?.pagination?.total || 0;
110
+ logger.info(` 📦 ${module.label}: ${itemCount} items`);
111
+ modulesWithData.push({
112
+ ...module,
113
+ slug: slugify(module.label),
114
+ data: dataResult.data?.data || [],
115
+ pagination: dataResult.data?.pagination || {
116
+ total: 0,
117
+ count: 0,
118
+ },
119
+ parameters: dataResult.data?.module?.parameters || {},
120
+ });
121
+ }
122
+ catch (error) {
123
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
124
+ logger.warn(` ⚠️ Failed to fetch ${module.label}: ${errorMessage}`);
125
+ modulesWithData.push({
126
+ ...module,
127
+ slug: slugify(module.label),
128
+ data: [],
129
+ pagination: { total: 0, count: 0 },
130
+ parameters: {},
131
+ });
132
+ }
133
+ }
134
+ // Create cache data
135
+ const cacheData = {
136
+ project: modulesResult.data.project,
137
+ modules: modulesWithData,
138
+ fetchedAt: new Date().toISOString(),
139
+ version: '1.0',
140
+ };
141
+ // Get the data directory path
142
+ const dataDir = path.join(process.cwd(), outputDir);
143
+ // Ensure directory exists
144
+ if (!fs.existsSync(dataDir)) {
145
+ fs.mkdirSync(dataDir, { recursive: true });
146
+ }
147
+ // Write cache file
148
+ const cachePath = path.join(dataDir, cacheFileName);
149
+ fs.writeFileSync(cachePath, JSON.stringify(cacheData, null, 2), 'utf-8');
150
+ logger.info(`✅ Cached data to: ${path.relative(process.cwd(), cachePath)}`);
151
+ logger.info(`📅 Fetched at: ${cacheData.fetchedAt}`);
152
+ }
153
+ catch (error) {
154
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
155
+ logger.error('❌ Failed to fetch CMS data:');
156
+ logger.error(` ${errorMessage}`);
157
+ if (skipOnError) {
158
+ logger.warn('⚠️ Continuing build without CMS data');
159
+ return;
160
+ }
161
+ throw error;
162
+ }
163
+ },
164
+ },
165
+ };
166
+ }
167
+ export default ayezeeCms;
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "ayezee-astro-cms",
3
+ "version": "1.0.0",
4
+ "description": "AyeZee CMS integration for Astro with automatic data fetching, form handling, and validation",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./integration": {
14
+ "types": "./dist/integration.d.ts",
15
+ "import": "./dist/integration.js"
16
+ },
17
+ "./components": {
18
+ "types": "./dist/components/index.d.ts",
19
+ "import": "./dist/components/index.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "README.md"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsc",
28
+ "dev": "tsc --watch",
29
+ "prepublishOnly": "npm run build"
30
+ },
31
+ "keywords": [
32
+ "astro",
33
+ "cms",
34
+ "ayezee",
35
+ "integration",
36
+ "form",
37
+ "validation"
38
+ ],
39
+ "author": "AyeZee Web Designs",
40
+ "license": "MIT",
41
+ "peerDependencies": {
42
+ "astro": "^4.0.0 || ^5.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "typescript": "^5.0.0",
46
+ "@types/node": "^20.0.0"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "https://github.com/ayezeewebdesigns/astro-cms.git"
51
+ }
52
+ }