nca-ai-cms-astro-plugin 1.0.3 → 1.0.5
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 +23 -10
- package/package.json +1 -1
- package/src/components/editor/SettingsTab.tsx +2 -2
- package/src/env.d.ts +12 -0
- package/src/index.ts +40 -2
- package/src/utils/envUtils.ts +4 -2
- package/task.md +77 -0
- package/update.md +34 -0
package/README.md
CHANGED
|
@@ -16,13 +16,14 @@ An Astro plugin that adds an AI-powered content editor to your site. Generate ar
|
|
|
16
16
|
### 1. Install
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
npm install nca-ai-cms-astro-plugin
|
|
19
|
+
npm install nca-ai-cms-astro-plugin @astrojs/node @astrojs/react @astrojs/db react react-dom @google/genai @google/generative-ai gray-matter marked sanitize-html sharp turndown zod
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
### 2. Add to your Astro config
|
|
23
23
|
|
|
24
|
-
```
|
|
24
|
+
```js
|
|
25
25
|
// astro.config.mjs
|
|
26
|
+
import { defineConfig } from 'astro/config';
|
|
26
27
|
import ncaAiCms from 'nca-ai-cms-astro-plugin';
|
|
27
28
|
|
|
28
29
|
export default defineConfig({
|
|
@@ -30,24 +31,36 @@ export default defineConfig({
|
|
|
30
31
|
});
|
|
31
32
|
```
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
The plugin auto-registers `react()`, `db()`, `output: 'server'`, and the `@astrojs/node` adapter. You can still set them manually if you need custom options.
|
|
35
|
+
|
|
36
|
+
### 3. Create `.env.local`
|
|
34
37
|
|
|
35
38
|
```env
|
|
39
|
+
EDITOR_ADMIN=admin
|
|
40
|
+
EDITOR_PASSWORD=your-secure-password
|
|
36
41
|
GOOGLE_GEMINI_API_KEY=your-gemini-api-key
|
|
37
|
-
EDITOR_ADMIN=your-username
|
|
38
|
-
EDITOR_PASSWORD=your-password
|
|
39
42
|
```
|
|
40
43
|
|
|
41
|
-
| Variable | Required |
|
|
44
|
+
| Variable | Required | Purpose |
|
|
42
45
|
|---|---|---|
|
|
46
|
+
| `EDITOR_ADMIN` | Yes | Login username for the editor |
|
|
47
|
+
| `EDITOR_PASSWORD` | Yes | Login password for the editor |
|
|
43
48
|
| `GOOGLE_GEMINI_API_KEY` | Yes | Google Gemini API key for content and image generation |
|
|
44
|
-
| `EDITOR_ADMIN` | Yes | Username for editor login |
|
|
45
|
-
| `EDITOR_PASSWORD` | Yes | Password for editor login |
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
Add `.env.local` to your `.gitignore` — never commit secrets.
|
|
51
|
+
|
|
52
|
+
### 4. Start the dev server
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx astro dev
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- Login: http://localhost:4321/login
|
|
59
|
+
- Editor: http://localhost:4321/editor (redirects to login if not authenticated)
|
|
60
|
+
|
|
61
|
+
### Requirements
|
|
48
62
|
|
|
49
63
|
- Astro 5+
|
|
50
|
-
- `@astrojs/db` and `@astrojs/react` integrations
|
|
51
64
|
- Node.js 18+
|
|
52
65
|
|
|
53
66
|
## Options
|
package/package.json
CHANGED
|
@@ -30,8 +30,8 @@ export function SettingsTab() {
|
|
|
30
30
|
try {
|
|
31
31
|
const res = await fetch('/api/prompts');
|
|
32
32
|
if (!res.ok) throw new Error('Fehler beim Laden der Einstellungen');
|
|
33
|
-
const data =
|
|
34
|
-
setPrompts(data);
|
|
33
|
+
const data = await res.json();
|
|
34
|
+
setPrompts(Array.isArray(data.prompts) ? data.prompts : []);
|
|
35
35
|
} catch (err) {
|
|
36
36
|
setError(
|
|
37
37
|
err instanceof Error ? err.message : 'Ein Fehler ist aufgetreten',
|
package/src/env.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface ImportMetaEnv {
|
|
2
|
+
readonly PROD: boolean;
|
|
3
|
+
readonly DEV: boolean;
|
|
4
|
+
readonly EDITOR_ADMIN: string;
|
|
5
|
+
readonly EDITOR_PASSWORD: string;
|
|
6
|
+
readonly GOOGLE_GEMINI_API_KEY: string;
|
|
7
|
+
readonly [key: string]: string | boolean | undefined;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface ImportMeta {
|
|
11
|
+
readonly env: ImportMetaEnv;
|
|
12
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { AstroIntegration } from 'astro';
|
|
2
|
+
import react from '@astrojs/react';
|
|
3
|
+
import db from '@astrojs/db';
|
|
4
|
+
import node from '@astrojs/node';
|
|
2
5
|
|
|
3
6
|
export interface NcaAiCmsPluginOptions {
|
|
4
7
|
contentPath?: string;
|
|
@@ -9,7 +12,7 @@ export default function ncaAiCms(
|
|
|
9
12
|
options: NcaAiCmsPluginOptions = {}
|
|
10
13
|
): AstroIntegration {
|
|
11
14
|
const contentPath = options.contentPath ?? 'nca-ai-cms-content';
|
|
12
|
-
const autoPublish = options.autoPublish ??
|
|
15
|
+
const autoPublish = options.autoPublish ?? import.meta.env.PROD;
|
|
13
16
|
|
|
14
17
|
return {
|
|
15
18
|
name: 'nca-ai-cms-astro-plugin',
|
|
@@ -20,12 +23,29 @@ export default function ncaAiCms(
|
|
|
20
23
|
});
|
|
21
24
|
},
|
|
22
25
|
|
|
23
|
-
'astro:config:setup'({ injectRoute, updateConfig, addMiddleware }) {
|
|
26
|
+
'astro:config:setup'({ injectRoute, updateConfig, addMiddleware, config }) {
|
|
24
27
|
addMiddleware({
|
|
25
28
|
entrypoint: 'nca-ai-cms-astro-plugin/middleware.ts',
|
|
26
29
|
order: 'pre',
|
|
27
30
|
});
|
|
28
31
|
|
|
32
|
+
// Auto-register react and db integrations if not already present
|
|
33
|
+
const hasReact = config.integrations.some((i) => i.name === '@astrojs/react');
|
|
34
|
+
if (!hasReact) {
|
|
35
|
+
config.integrations.push(react());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const hasDb = config.integrations.some((i) => i.name === '@astrojs/db');
|
|
39
|
+
if (!hasDb) {
|
|
40
|
+
config.integrations.push(...(db() as unknown as AstroIntegration[]));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Auto-configure server output and node adapter
|
|
44
|
+
updateConfig({
|
|
45
|
+
output: 'server' as const,
|
|
46
|
+
adapter: node({ mode: 'standalone' }),
|
|
47
|
+
});
|
|
48
|
+
|
|
29
49
|
// Virtual module for config sharing
|
|
30
50
|
updateConfig({
|
|
31
51
|
vite: {
|
|
@@ -51,80 +71,98 @@ export default function ncaAiCms(
|
|
|
51
71
|
injectRoute({
|
|
52
72
|
pattern: '/api/generate-content',
|
|
53
73
|
entrypoint: 'nca-ai-cms-astro-plugin/api/generate-content.ts',
|
|
74
|
+
prerender: false,
|
|
54
75
|
});
|
|
55
76
|
injectRoute({
|
|
56
77
|
pattern: '/api/generate-image',
|
|
57
78
|
entrypoint: 'nca-ai-cms-astro-plugin/api/generate-image.ts',
|
|
79
|
+
prerender: false,
|
|
58
80
|
});
|
|
59
81
|
injectRoute({
|
|
60
82
|
pattern: '/api/save',
|
|
61
83
|
entrypoint: 'nca-ai-cms-astro-plugin/api/save.ts',
|
|
84
|
+
prerender: false,
|
|
62
85
|
});
|
|
63
86
|
injectRoute({
|
|
64
87
|
pattern: '/api/save-image',
|
|
65
88
|
entrypoint: 'nca-ai-cms-astro-plugin/api/save-image.ts',
|
|
89
|
+
prerender: false,
|
|
66
90
|
});
|
|
67
91
|
injectRoute({
|
|
68
92
|
pattern: '/api/prompts',
|
|
69
93
|
entrypoint: 'nca-ai-cms-astro-plugin/api/prompts.ts',
|
|
94
|
+
prerender: false,
|
|
70
95
|
});
|
|
71
96
|
injectRoute({
|
|
72
97
|
pattern: '/api/scheduler',
|
|
73
98
|
entrypoint: 'nca-ai-cms-astro-plugin/api/scheduler.ts',
|
|
99
|
+
prerender: false,
|
|
74
100
|
});
|
|
75
101
|
injectRoute({
|
|
76
102
|
pattern: '/api/scheduler/generate',
|
|
77
103
|
entrypoint: 'nca-ai-cms-astro-plugin/api/scheduler/generate.ts',
|
|
104
|
+
prerender: false,
|
|
78
105
|
});
|
|
79
106
|
injectRoute({
|
|
80
107
|
pattern: '/api/scheduler/publish',
|
|
81
108
|
entrypoint: 'nca-ai-cms-astro-plugin/api/scheduler/publish.ts',
|
|
109
|
+
prerender: false,
|
|
82
110
|
});
|
|
83
111
|
injectRoute({
|
|
84
112
|
pattern: '/api/scheduler/[id]',
|
|
85
113
|
entrypoint: 'nca-ai-cms-astro-plugin/api/scheduler/[id].ts',
|
|
114
|
+
prerender: false,
|
|
86
115
|
});
|
|
87
116
|
injectRoute({
|
|
88
117
|
pattern: '/api/articles/[id]',
|
|
89
118
|
entrypoint: 'nca-ai-cms-astro-plugin/api/articles/[id].ts',
|
|
119
|
+
prerender: false,
|
|
90
120
|
});
|
|
91
121
|
injectRoute({
|
|
92
122
|
pattern: '/api/articles/[id]/apply',
|
|
93
123
|
entrypoint: 'nca-ai-cms-astro-plugin/api/articles/[id]/apply.ts',
|
|
124
|
+
prerender: false,
|
|
94
125
|
});
|
|
95
126
|
injectRoute({
|
|
96
127
|
pattern: '/api/articles/[id]/regenerate-text',
|
|
97
128
|
entrypoint:
|
|
98
129
|
'nca-ai-cms-astro-plugin/api/articles/[id]/regenerate-text.ts',
|
|
130
|
+
prerender: false,
|
|
99
131
|
});
|
|
100
132
|
injectRoute({
|
|
101
133
|
pattern: '/api/articles/[id]/regenerate-image',
|
|
102
134
|
entrypoint:
|
|
103
135
|
'nca-ai-cms-astro-plugin/api/articles/[id]/regenerate-image.ts',
|
|
136
|
+
prerender: false,
|
|
104
137
|
});
|
|
105
138
|
|
|
106
139
|
// Inject auth routes
|
|
107
140
|
injectRoute({
|
|
108
141
|
pattern: '/api/auth/login',
|
|
109
142
|
entrypoint: 'nca-ai-cms-astro-plugin/api/auth/login.ts',
|
|
143
|
+
prerender: false,
|
|
110
144
|
});
|
|
111
145
|
injectRoute({
|
|
112
146
|
pattern: '/api/auth/logout',
|
|
113
147
|
entrypoint: 'nca-ai-cms-astro-plugin/api/auth/logout.ts',
|
|
148
|
+
prerender: false,
|
|
114
149
|
});
|
|
115
150
|
injectRoute({
|
|
116
151
|
pattern: '/api/auth/check',
|
|
117
152
|
entrypoint: 'nca-ai-cms-astro-plugin/api/auth/check.ts',
|
|
153
|
+
prerender: false,
|
|
118
154
|
});
|
|
119
155
|
|
|
120
156
|
// Inject pages
|
|
121
157
|
injectRoute({
|
|
122
158
|
pattern: '/login',
|
|
123
159
|
entrypoint: 'nca-ai-cms-astro-plugin/pages/login.astro',
|
|
160
|
+
prerender: false,
|
|
124
161
|
});
|
|
125
162
|
injectRoute({
|
|
126
163
|
pattern: '/editor',
|
|
127
164
|
entrypoint: 'nca-ai-cms-astro-plugin/pages/editor.astro',
|
|
165
|
+
prerender: false,
|
|
128
166
|
});
|
|
129
167
|
},
|
|
130
168
|
|
package/src/utils/envUtils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Reads an environment variable from `
|
|
2
|
+
* Reads an environment variable from `import.meta.env` (Astro/Vite)
|
|
3
|
+
* with a fallback to `process.env` for non-Vite environments.
|
|
3
4
|
*
|
|
4
5
|
* @param variable - The name of the environment variable.
|
|
5
6
|
* @param defaultValue - Optional fallback when the variable is not set.
|
|
@@ -10,7 +11,8 @@ export function getEnvVariable(
|
|
|
10
11
|
variable: string,
|
|
11
12
|
defaultValue?: string,
|
|
12
13
|
): string {
|
|
13
|
-
const value =
|
|
14
|
+
const value = (import.meta.env as Record<string, string | undefined>)[variable]
|
|
15
|
+
?? process.env[variable];
|
|
14
16
|
|
|
15
17
|
if (value !== undefined && value !== "") {
|
|
16
18
|
return value;
|
package/task.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Fix nca-ai-cms-astro-plugin v1.0.5
|
|
2
|
+
|
|
3
|
+
## 1. Fix SettingsTab.tsx response parsing
|
|
4
|
+
|
|
5
|
+
**File:** `src/components/editor/SettingsTab.tsx`
|
|
6
|
+
|
|
7
|
+
Line 33-34: API `/api/prompts` returns `{ prompts, settings }` but the component casts the entire response as `Prompt[]`, causing a crash.
|
|
8
|
+
|
|
9
|
+
```diff
|
|
10
|
+
- const data = (await res.json()) as Prompt[];
|
|
11
|
+
- setPrompts(data);
|
|
12
|
+
+ const data = await res.json();
|
|
13
|
+
+ setPrompts(Array.isArray(data.prompts) ? data.prompts : []);
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 2. Auto-register dependencies in index.ts
|
|
17
|
+
|
|
18
|
+
**File:** `src/index.ts`
|
|
19
|
+
|
|
20
|
+
The consumer currently must manually add `react()`, `db()`, `output: 'server'`, and the node adapter. The plugin should handle this automatically in `astro:config:setup`.
|
|
21
|
+
|
|
22
|
+
- Import `@astrojs/react`, `@astrojs/db`, `@astrojs/node` at the top
|
|
23
|
+
- Add `addIntegration` and `config` to the hook destructuring
|
|
24
|
+
- Check `config.integrations` for existing react/db before adding
|
|
25
|
+
- Call `updateConfig()` with `output: 'server'` and `adapter: node({ mode: 'standalone' })`
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
'astro:config:setup'({ injectRoute, updateConfig, addMiddleware, addIntegration, config }) {
|
|
29
|
+
const hasReact = config.integrations.some((i) => i.name === '@astrojs/react');
|
|
30
|
+
if (!hasReact) {
|
|
31
|
+
addIntegration(react());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const hasDb = config.integrations.some((i) => i.name === '@astrojs/db');
|
|
35
|
+
if (!hasDb) {
|
|
36
|
+
addIntegration(db());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
updateConfig({
|
|
40
|
+
output: 'server' as const,
|
|
41
|
+
adapter: node({ mode: 'standalone' }),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// ... rest of hook unchanged
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 3. Bump version to 1.0.5
|
|
49
|
+
|
|
50
|
+
**File:** `package.json`
|
|
51
|
+
|
|
52
|
+
Change `"version": "1.0.4"` to `"version": "1.0.5"`.
|
|
53
|
+
|
|
54
|
+
## 4. Update README with simplified setup
|
|
55
|
+
|
|
56
|
+
**File:** `README.md`
|
|
57
|
+
|
|
58
|
+
Update setup instructions to reflect that the consumer only needs:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import ncaAiCms from 'nca-ai-cms-astro-plugin';
|
|
62
|
+
|
|
63
|
+
export default defineConfig({
|
|
64
|
+
integrations: [ncaAiCms()],
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Add `.env.local` step with `GOOGLE_GEMINI_API_KEY`, `EDITOR_ADMIN`, `EDITOR_PASSWORD`.
|
|
69
|
+
|
|
70
|
+
Note that `prerender: false` is already present on all 18 `injectRoute()` calls — no changes needed there.
|
|
71
|
+
|
|
72
|
+
## Verification
|
|
73
|
+
|
|
74
|
+
1. In a test project, use only `integrations: [ncaAiCms()]` in astro config
|
|
75
|
+
2. Run `npx astro dev`
|
|
76
|
+
3. Open `/login` — should render without errors
|
|
77
|
+
4. Log in, open `/editor` — settings tab should load without crash
|
package/update.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# v1.0.5
|
|
2
|
+
|
|
3
|
+
## Fix: SettingsTab crash on prompts response
|
|
4
|
+
- `/api/prompts` returns `{ prompts, settings }` but SettingsTab cast the entire response as `Prompt[]`
|
|
5
|
+
- Fixed to extract `data.prompts` from the response object
|
|
6
|
+
|
|
7
|
+
## Auto-register dependencies
|
|
8
|
+
- Plugin now auto-configures `output: 'server'`, `@astrojs/node` adapter, `react()`, and `db()` via `updateConfig()`
|
|
9
|
+
- Consumer config is now just `integrations: [ncaAiCms()]`
|
|
10
|
+
- Existing manual config is respected — auto-registration only kicks in when not already set
|
|
11
|
+
|
|
12
|
+
## Setup guide in README
|
|
13
|
+
- Full install command with all peer dependencies
|
|
14
|
+
- `.env.local` setup with variable reference table
|
|
15
|
+
- Minimal `astro.config.mjs` example
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# v1.0.4
|
|
20
|
+
|
|
21
|
+
## Fix: Environment variables and route prerendering
|
|
22
|
+
|
|
23
|
+
### Environment variables now work with Astro's .env files
|
|
24
|
+
- `getEnvVariable()` now reads from `import.meta.env` first, with a `process.env` fallback
|
|
25
|
+
- Previously only checked `process.env`, which meant `.env` / `.env.local` files were ignored in Astro dev and SSR
|
|
26
|
+
- Works in all environments: local dev, Docker, GitLab CI/CD
|
|
27
|
+
|
|
28
|
+
### All injected routes are now server-rendered
|
|
29
|
+
- Added `prerender: false` to all 18 injected routes (API, auth, pages)
|
|
30
|
+
- Consumers no longer need to set `output: 'server'` globally in their Astro config
|
|
31
|
+
- The plugin works with Astro's default `output: 'static'` — only plugin routes are server-rendered
|
|
32
|
+
|
|
33
|
+
### Minor: use `import.meta.env.PROD` for auto-publish check
|
|
34
|
+
- Replaced `process.env.NODE_ENV === 'production'` with Astro's built-in `import.meta.env.PROD`
|