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 +240 -0
- package/dist/cms-helper.d.ts +176 -0
- package/dist/cms-helper.js +190 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +13 -0
- package/dist/integration.d.ts +48 -0
- package/dist/integration.js +167 -0
- package/package.json +52 -0
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
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|