@kyro-cms/core 0.1.1 → 0.1.3
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 +202 -113
- package/dist/bootstrap-2WJK6PG7.cjs +29 -0
- package/dist/bootstrap-2WJK6PG7.cjs.map +1 -0
- package/dist/bootstrap-Q2TWUQF3.js +4 -0
- package/dist/bootstrap-Q2TWUQF3.js.map +1 -0
- package/dist/chunk-3QX6KG2S.js +2125 -0
- package/dist/chunk-3QX6KG2S.js.map +1 -0
- package/dist/chunk-5AOILNGY.cjs +212 -0
- package/dist/chunk-5AOILNGY.cjs.map +1 -0
- package/dist/{chunk-DKSMFC3L.js → chunk-EINVJPFM.js} +2 -2
- package/dist/{chunk-DKSMFC3L.js.map → chunk-EINVJPFM.js.map} +1 -1
- package/dist/chunk-F5B64H5S.cjs +2149 -0
- package/dist/chunk-F5B64H5S.cjs.map +1 -0
- package/dist/chunk-I4BORBXT.cjs +914 -0
- package/dist/chunk-I4BORBXT.cjs.map +1 -0
- package/dist/chunk-KA3UOIFC.js +206 -0
- package/dist/chunk-KA3UOIFC.js.map +1 -0
- package/dist/chunk-KWTKEBHM.cjs +176 -0
- package/dist/chunk-KWTKEBHM.cjs.map +1 -0
- package/dist/chunk-M4JFHQ5J.js +170 -0
- package/dist/chunk-M4JFHQ5J.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +9 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-Q7SFCCGT.cjs +11 -0
- package/dist/chunk-Q7SFCCGT.cjs.map +1 -0
- package/dist/chunk-U4CHJTWX.cjs +94 -0
- package/dist/chunk-U4CHJTWX.cjs.map +1 -0
- package/dist/{chunk-3Q3FS5J4.cjs → chunk-V3B25QOK.cjs} +2 -2
- package/dist/{chunk-3Q3FS5J4.cjs.map → chunk-V3B25QOK.cjs.map} +1 -1
- package/dist/chunk-V67YXRBT.js +899 -0
- package/dist/chunk-V67YXRBT.js.map +1 -0
- package/dist/chunk-XLMVCGXA.js +86 -0
- package/dist/chunk-XLMVCGXA.js.map +1 -0
- package/dist/cli/index.cjs +106 -14
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +106 -14
- package/dist/cli/index.js.map +1 -1
- package/dist/database-37KXWUER.js +5 -0
- package/dist/database-37KXWUER.js.map +1 -0
- package/dist/database-LJKD3HE4.cjs +22 -0
- package/dist/database-LJKD3HE4.cjs.map +1 -0
- package/dist/drizzle/index.cjs +25 -5
- package/dist/drizzle/index.d.cts +5 -49
- package/dist/drizzle/index.d.ts +5 -49
- package/dist/drizzle/index.js +5 -1
- package/dist/graphql/index.cjs +1 -0
- package/dist/graphql/index.js +1 -0
- package/dist/index-BVFlb7uU.d.ts +192 -0
- package/dist/index-CzkEHKqu.d.cts +192 -0
- package/dist/index.cjs +1479 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +421 -65
- package/dist/index.d.ts +421 -65
- package/dist/index.js +1384 -22
- package/dist/index.js.map +1 -1
- package/dist/mongodb/index.cjs +1 -0
- package/dist/mongodb/index.js +1 -0
- package/dist/postgres-auth-adapter-CYZAVPPP.cjs +14 -0
- package/dist/postgres-auth-adapter-CYZAVPPP.cjs.map +1 -0
- package/dist/postgres-auth-adapter-LTDUGBMB.js +5 -0
- package/dist/postgres-auth-adapter-LTDUGBMB.js.map +1 -0
- package/dist/rest/index.cjs +1 -0
- package/dist/rest/index.js +1 -0
- package/dist/templates/index.cjs +94 -536
- package/dist/templates/index.cjs.map +1 -1
- package/dist/templates/index.d.cts +45 -1
- package/dist/templates/index.d.ts +45 -1
- package/dist/templates/index.js +2 -535
- package/dist/templates/index.js.map +1 -1
- package/dist/trpc/index.cjs +1 -0
- package/dist/trpc/index.js +1 -0
- package/dist/ws/index.cjs +1 -0
- package/dist/ws/index.js +1 -0
- package/package.json +23 -8
package/README.md
CHANGED
|
@@ -18,8 +18,8 @@ Kyro is built for **Astro** from the ground up. Unlike other CMS solutions that
|
|
|
18
18
|
|
|
19
19
|
### Key Features
|
|
20
20
|
|
|
21
|
-
- **
|
|
22
|
-
- **Multi-Database** - SQLite, PostgreSQL, MySQL, MongoDB via unified adapter interface
|
|
21
|
+
- **Zero-Config Development** - SQLite by default for instant setup, no external dependencies
|
|
22
|
+
- **Multi-Database** - SQLite (dev), PostgreSQL, MySQL, MongoDB via unified adapter interface
|
|
23
23
|
- **Multi-Protocol API** - REST, GraphQL, tRPC, and WebSocket from a single config
|
|
24
24
|
- **Multi-Vendor** - Built-in tenant scoping and row-level access control
|
|
25
25
|
- **E-Commerce Ready** - Products, orders, customers, inventory, coupons out of the box
|
|
@@ -37,6 +37,7 @@ npm create kyro@latest
|
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
This launches an interactive wizard that asks:
|
|
40
|
+
|
|
40
41
|
- Project name
|
|
41
42
|
- Database (SQLite, PostgreSQL, MySQL, MongoDB)
|
|
42
43
|
- API protocols (REST, GraphQL, tRPC, WebSocket)
|
|
@@ -54,20 +55,20 @@ npm install @kyro-cms/core
|
|
|
54
55
|
|
|
55
56
|
```typescript
|
|
56
57
|
// kyro.config.ts
|
|
57
|
-
import { defineConfig, localAdapter } from
|
|
58
|
+
import { defineConfig, localAdapter } from "@kyro-cms/core";
|
|
58
59
|
|
|
59
60
|
export default defineConfig({
|
|
60
|
-
name:
|
|
61
|
-
adapter: localAdapter({ path:
|
|
61
|
+
name: "my-app",
|
|
62
|
+
adapter: localAdapter({ path: "./data.db" }),
|
|
62
63
|
collections: {
|
|
63
64
|
posts: {
|
|
64
|
-
slug:
|
|
65
|
-
label:
|
|
65
|
+
slug: "posts",
|
|
66
|
+
label: "Posts",
|
|
66
67
|
fields: [
|
|
67
|
-
{ name:
|
|
68
|
-
{ name:
|
|
69
|
-
{ name:
|
|
70
|
-
{ name:
|
|
68
|
+
{ name: "title", type: "text", required: true },
|
|
69
|
+
{ name: "slug", type: "text", required: true },
|
|
70
|
+
{ name: "content", type: "richtext" },
|
|
71
|
+
{ name: "published", type: "checkbox", defaultValue: false },
|
|
71
72
|
],
|
|
72
73
|
},
|
|
73
74
|
},
|
|
@@ -82,22 +83,22 @@ export default defineConfig({
|
|
|
82
83
|
|
|
83
84
|
## Database Adapters
|
|
84
85
|
|
|
85
|
-
### SQLite (
|
|
86
|
+
### SQLite (Default for Development)
|
|
86
87
|
|
|
87
88
|
```typescript
|
|
88
|
-
import { localAdapter } from
|
|
89
|
+
import { localAdapter } from "@kyro-cms/core";
|
|
89
90
|
|
|
90
91
|
const adapter = localAdapter({
|
|
91
|
-
path:
|
|
92
|
+
path: "./data.db", // or ':memory:' for in-memory
|
|
92
93
|
});
|
|
93
94
|
```
|
|
94
95
|
|
|
95
|
-
Perfect for development and small projects. Zero configuration required.
|
|
96
|
+
Perfect for development and small projects. Zero configuration required - no external services needed.
|
|
96
97
|
|
|
97
98
|
### PostgreSQL/MySQL (Production)
|
|
98
99
|
|
|
99
100
|
```typescript
|
|
100
|
-
import { drizzleAdapter } from
|
|
101
|
+
import { drizzleAdapter } from "@kyro-cms/core";
|
|
101
102
|
|
|
102
103
|
const adapter = drizzleAdapter({
|
|
103
104
|
connectionString: process.env.DATABASE_URL,
|
|
@@ -107,7 +108,7 @@ const adapter = drizzleAdapter({
|
|
|
107
108
|
### MongoDB (Flexible Schemas)
|
|
108
109
|
|
|
109
110
|
```typescript
|
|
110
|
-
import { mongoAdapter } from
|
|
111
|
+
import { mongoAdapter } from "@kyro-cms/core";
|
|
111
112
|
|
|
112
113
|
const adapter = mongoAdapter({
|
|
113
114
|
connectionString: process.env.MONGODB_URI,
|
|
@@ -177,20 +178,22 @@ const client = createTRPCClient({
|
|
|
177
178
|
const posts = await client.posts.find.query({ page: 1 });
|
|
178
179
|
const newPost = await client.posts.create.mutate({
|
|
179
180
|
title: "Hello",
|
|
180
|
-
slug: "hello"
|
|
181
|
+
slug: "hello",
|
|
181
182
|
});
|
|
182
183
|
```
|
|
183
184
|
|
|
184
185
|
### WebSocket (Real-time)
|
|
185
186
|
|
|
186
187
|
```typescript
|
|
187
|
-
const ws = new WebSocket(
|
|
188
|
+
const ws = new WebSocket("ws://localhost:4321/api/ws");
|
|
188
189
|
|
|
189
|
-
ws.send(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
190
|
+
ws.send(
|
|
191
|
+
JSON.stringify({
|
|
192
|
+
type: "subscribe",
|
|
193
|
+
collection: "posts",
|
|
194
|
+
event: "create",
|
|
195
|
+
}),
|
|
196
|
+
);
|
|
194
197
|
|
|
195
198
|
ws.onmessage = (event) => {
|
|
196
199
|
const data = JSON.parse(event.data);
|
|
@@ -204,62 +207,62 @@ ws.onmessage = (event) => {
|
|
|
204
207
|
|
|
205
208
|
Kyro supports 21 field types:
|
|
206
209
|
|
|
207
|
-
| Type
|
|
208
|
-
|
|
209
|
-
| `text`
|
|
210
|
-
| `textarea`
|
|
211
|
-
| `richtext`
|
|
212
|
-
| `markdown`
|
|
213
|
-
| `number`
|
|
214
|
-
| `email`
|
|
215
|
-
| `password`
|
|
216
|
-
| `checkbox`
|
|
217
|
-
| `date`
|
|
218
|
-
| `select`
|
|
219
|
-
| `radio`
|
|
220
|
-
| `color`
|
|
221
|
-
| `json`
|
|
222
|
-
| `code`
|
|
223
|
-
| `array`
|
|
224
|
-
| `group`
|
|
225
|
-
| `relationship` | Link to other documents
|
|
226
|
-
| `upload`
|
|
227
|
-
| `blocks`
|
|
228
|
-
| `row`
|
|
229
|
-
| `collapsible`
|
|
230
|
-
| `tabs`
|
|
210
|
+
| Type | Description |
|
|
211
|
+
| -------------- | -------------------------- |
|
|
212
|
+
| `text` | Single-line text input |
|
|
213
|
+
| `textarea` | Multi-line text |
|
|
214
|
+
| `richtext` | Rich text editor content |
|
|
215
|
+
| `markdown` | Markdown content |
|
|
216
|
+
| `number` | Numeric values |
|
|
217
|
+
| `email` | Email with validation |
|
|
218
|
+
| `password` | Hashed password storage |
|
|
219
|
+
| `checkbox` | Boolean toggle |
|
|
220
|
+
| `date` | Date/time picker |
|
|
221
|
+
| `select` | Dropdown selection |
|
|
222
|
+
| `radio` | Radio button group |
|
|
223
|
+
| `color` | Color picker |
|
|
224
|
+
| `json` | JSON data |
|
|
225
|
+
| `code` | Code editor content |
|
|
226
|
+
| `array` | Repeatable field groups |
|
|
227
|
+
| `group` | Nested field groups |
|
|
228
|
+
| `relationship` | Link to other documents |
|
|
229
|
+
| `upload` | File/media uploads |
|
|
230
|
+
| `blocks` | Structured content blocks |
|
|
231
|
+
| `row` | Horizontal field layout |
|
|
232
|
+
| `collapsible` | Collapsible field sections |
|
|
233
|
+
| `tabs` | Tabbed interface |
|
|
231
234
|
|
|
232
235
|
### Example: Complex Fields
|
|
233
236
|
|
|
234
237
|
```typescript
|
|
235
238
|
fields: [
|
|
236
|
-
{ name:
|
|
237
|
-
|
|
239
|
+
{ name: "title", type: "text", required: true },
|
|
240
|
+
|
|
238
241
|
{
|
|
239
|
-
name:
|
|
240
|
-
type:
|
|
241
|
-
relationTo:
|
|
242
|
-
required: true
|
|
242
|
+
name: "author",
|
|
243
|
+
type: "relationship",
|
|
244
|
+
relationTo: "users",
|
|
245
|
+
required: true,
|
|
243
246
|
},
|
|
244
|
-
|
|
247
|
+
|
|
245
248
|
{
|
|
246
|
-
name:
|
|
247
|
-
type:
|
|
249
|
+
name: "tags",
|
|
250
|
+
type: "array",
|
|
248
251
|
fields: [
|
|
249
|
-
{ name:
|
|
250
|
-
{ name:
|
|
251
|
-
]
|
|
252
|
+
{ name: "name", type: "text" },
|
|
253
|
+
{ name: "slug", type: "text" },
|
|
254
|
+
],
|
|
252
255
|
},
|
|
253
|
-
|
|
256
|
+
|
|
254
257
|
{
|
|
255
|
-
name:
|
|
256
|
-
type:
|
|
258
|
+
name: "metadata",
|
|
259
|
+
type: "group",
|
|
257
260
|
fields: [
|
|
258
|
-
{ name:
|
|
259
|
-
{ name:
|
|
260
|
-
]
|
|
261
|
-
}
|
|
262
|
-
]
|
|
261
|
+
{ name: "views", type: "number", defaultValue: 0 },
|
|
262
|
+
{ name: "featured", type: "checkbox" },
|
|
263
|
+
],
|
|
264
|
+
},
|
|
265
|
+
];
|
|
263
266
|
```
|
|
264
267
|
|
|
265
268
|
---
|
|
@@ -269,10 +272,10 @@ fields: [
|
|
|
269
272
|
Pre-built collections for building online stores:
|
|
270
273
|
|
|
271
274
|
```typescript
|
|
272
|
-
import { ecommerceCollections } from
|
|
275
|
+
import { ecommerceCollections } from "@kyro-cms/core";
|
|
273
276
|
|
|
274
277
|
const kyro = createKyro({
|
|
275
|
-
adapter: localAdapter({ path:
|
|
278
|
+
adapter: localAdapter({ path: "./store.db" }),
|
|
276
279
|
collections: ecommerceCollections,
|
|
277
280
|
});
|
|
278
281
|
|
|
@@ -289,31 +292,83 @@ const kyro = createKyro({
|
|
|
289
292
|
|
|
290
293
|
## Authentication
|
|
291
294
|
|
|
292
|
-
Built-in JWT authentication:
|
|
295
|
+
Built-in JWT authentication with multiple storage options:
|
|
293
296
|
|
|
294
297
|
```typescript
|
|
295
|
-
import {
|
|
298
|
+
import { RedisAuthAdapter, SQLiteAuthAdapter } from "@kyro-cms/core";
|
|
299
|
+
import { createAuthConfig } from "@kyro-cms/core";
|
|
296
300
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
expiresIn: '24h',
|
|
300
|
-
refreshExpiresIn: '7d',
|
|
301
|
-
});
|
|
301
|
+
// Use SQLite for development (zero-config, default)
|
|
302
|
+
const adapter = new SQLiteAuthAdapter({ path: "./data.db" });
|
|
302
303
|
|
|
303
|
-
//
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
role: 'customer',
|
|
304
|
+
// Use Redis for sessions (recommended for production)
|
|
305
|
+
const redisAdapter = new RedisAuthAdapter({
|
|
306
|
+
url: process.env.REDIS_URL,
|
|
307
|
+
tls: process.env.REDIS_TLS === "true",
|
|
308
308
|
});
|
|
309
309
|
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
});
|
|
310
|
+
// Or use PostgreSQL for production
|
|
311
|
+
import { PostgresAuthAdapter, createDatabase } from "@kyro-cms/core";
|
|
312
|
+
|
|
313
|
+
const { db } = await createDatabase();
|
|
314
|
+
const pgAdapter = new PostgresAuthAdapter({ db });
|
|
315
|
+
|
|
316
|
+
// Or use env-based config with all features
|
|
317
|
+
const authConfig = await createAuthConfig();
|
|
318
|
+
const { redis, routes, passwordPolicy, lockout } = authConfig;
|
|
319
|
+
```
|
|
315
320
|
|
|
316
|
-
|
|
321
|
+
### Authentication Features
|
|
322
|
+
|
|
323
|
+
- **JWT Tokens** - 24h expiry with refresh token support
|
|
324
|
+
- **Multiple Storage Options** - SQLite (dev), Redis, PostgreSQL via unified adapter interface
|
|
325
|
+
- **Password Policy** - 12+ chars, complexity requirements, history check
|
|
326
|
+
- **Account Lockout** - 5 failed attempts → 15 minute lockout
|
|
327
|
+
- **Rate Limiting** - Per-IP and per-user limits
|
|
328
|
+
- **Audit Logging** - 30-day retention with action tracking
|
|
329
|
+
|
|
330
|
+
### CLI Commands
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
# Create admin user (first-run bootstrap)
|
|
334
|
+
kyro auth bootstrap -e admin@example.com -p "SecurePass123!" -r admin
|
|
335
|
+
|
|
336
|
+
# Database setup
|
|
337
|
+
kyro db migrate # Run migrations
|
|
338
|
+
kyro db push # Push schema to database
|
|
339
|
+
kyro db seed # Seed default roles
|
|
340
|
+
kyro db studio # Open Drizzle Studio
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### RBAC Roles (Hierarchy)
|
|
344
|
+
|
|
345
|
+
```
|
|
346
|
+
super_admin (100) > admin (90) > editor (70) > author (50) > customer (30) > guest (10)
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Environment Variables
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
# Database
|
|
353
|
+
DATABASE_URL=postgresql://user:pass@host:5432/kyro_cms
|
|
354
|
+
DATABASE_SSL=false
|
|
355
|
+
|
|
356
|
+
# Redis (sessions/cache)
|
|
357
|
+
REDIS_URL=redis://localhost:6379
|
|
358
|
+
REDIS_TLS=false
|
|
359
|
+
|
|
360
|
+
# JWT
|
|
361
|
+
JWT_SECRET=your-32-char-secret
|
|
362
|
+
JWT_EXPIRES_IN=24h
|
|
363
|
+
|
|
364
|
+
# Auth Settings
|
|
365
|
+
LOCKOUT_MAX_ATTEMPTS=5
|
|
366
|
+
LOCKOUT_DURATION_MINUTES=15
|
|
367
|
+
PASSWORD_MIN_LENGTH=12
|
|
368
|
+
|
|
369
|
+
# Bootstrap (first-run admin)
|
|
370
|
+
KYRO_ADMIN_EMAIL=admin@example.com
|
|
371
|
+
KYRO_ADMIN_PASSWORD=SecurePass123!
|
|
317
372
|
```
|
|
318
373
|
|
|
319
374
|
---
|
|
@@ -323,7 +378,7 @@ console.log(result.token); // JWT token
|
|
|
323
378
|
Track document changes with built-in versioning:
|
|
324
379
|
|
|
325
380
|
```typescript
|
|
326
|
-
import { createVersionManager } from
|
|
381
|
+
import { createVersionManager } from "@kyro-cms/core";
|
|
327
382
|
|
|
328
383
|
const versions = createVersionManager(adapter, {
|
|
329
384
|
versioningEnabled: true,
|
|
@@ -332,19 +387,19 @@ const versions = createVersionManager(adapter, {
|
|
|
332
387
|
|
|
333
388
|
// Create a new version
|
|
334
389
|
const version = await versions.createVersion({
|
|
335
|
-
collection:
|
|
336
|
-
documentId:
|
|
337
|
-
data: { title:
|
|
338
|
-
status:
|
|
339
|
-
createdBy:
|
|
390
|
+
collection: "posts",
|
|
391
|
+
documentId: "abc123",
|
|
392
|
+
data: { title: "Updated Post" },
|
|
393
|
+
status: "draft",
|
|
394
|
+
createdBy: "user123",
|
|
340
395
|
});
|
|
341
396
|
|
|
342
397
|
// Publish
|
|
343
398
|
await versions.publishVersion({
|
|
344
|
-
collection:
|
|
345
|
-
documentId:
|
|
399
|
+
collection: "posts",
|
|
400
|
+
documentId: "abc123",
|
|
346
401
|
versionId: version.id,
|
|
347
|
-
publishedBy:
|
|
402
|
+
publishedBy: "user123",
|
|
348
403
|
});
|
|
349
404
|
```
|
|
350
405
|
|
|
@@ -369,6 +424,7 @@ import config from '../kyro.config';
|
|
|
369
424
|
```
|
|
370
425
|
|
|
371
426
|
Features:
|
|
427
|
+
|
|
372
428
|
- Collection browser with filtering and sorting
|
|
373
429
|
- Document editor with all field types
|
|
374
430
|
- Media library
|
|
@@ -382,13 +438,13 @@ Features:
|
|
|
382
438
|
Extend Kyro with plugins:
|
|
383
439
|
|
|
384
440
|
```typescript
|
|
385
|
-
import {
|
|
441
|
+
import {
|
|
386
442
|
KyroPlugin,
|
|
387
443
|
SEOPLugin,
|
|
388
444
|
AnalyticsPlugin,
|
|
389
445
|
CommentsPlugin,
|
|
390
446
|
ReviewsPlugin,
|
|
391
|
-
WishlistPlugin
|
|
447
|
+
WishlistPlugin
|
|
392
448
|
} from '@kyro-cms/core';
|
|
393
449
|
|
|
394
450
|
const kyro = createKyro({
|
|
@@ -411,18 +467,18 @@ const kyro = createKyro({
|
|
|
411
467
|
### Creating Plugins
|
|
412
468
|
|
|
413
469
|
```typescript
|
|
414
|
-
import { KyroPlugin } from
|
|
470
|
+
import { KyroPlugin } from "@kyro-cms/core";
|
|
415
471
|
|
|
416
472
|
class MyPlugin extends KyroPlugin {
|
|
417
|
-
name =
|
|
418
|
-
|
|
473
|
+
name = "my-plugin";
|
|
474
|
+
|
|
419
475
|
hooks = {
|
|
420
|
-
|
|
476
|
+
"collection.beforeCreate": async (args) => {
|
|
421
477
|
// Transform data before creation
|
|
422
|
-
return { ...args, data: { ...args.data, source:
|
|
478
|
+
return { ...args, data: { ...args.data, source: "my-plugin" } };
|
|
423
479
|
},
|
|
424
|
-
|
|
425
|
-
|
|
480
|
+
|
|
481
|
+
"document.afterSave": async (args) => {
|
|
426
482
|
// Send webhook, log analytics, etc.
|
|
427
483
|
await sendWebhook(args);
|
|
428
484
|
},
|
|
@@ -437,11 +493,11 @@ class MyPlugin extends KyroPlugin {
|
|
|
437
493
|
Kyro ships with a complete styling system:
|
|
438
494
|
|
|
439
495
|
```typescript
|
|
440
|
-
import {
|
|
496
|
+
import {
|
|
441
497
|
ecommerce2026Theme,
|
|
442
498
|
generateCSSVariables,
|
|
443
|
-
generateTailwindConfig
|
|
444
|
-
} from
|
|
499
|
+
generateTailwindConfig,
|
|
500
|
+
} from "@kyro-cms/core";
|
|
445
501
|
|
|
446
502
|
// Generate CSS variables
|
|
447
503
|
const cssVars = generateCSSVariables(ecommerce2026Theme);
|
|
@@ -450,12 +506,12 @@ const cssVars = generateCSSVariables(ecommerce2026Theme);
|
|
|
450
506
|
const tailwindConfig = generateTailwindConfig(ecommerce2026Theme);
|
|
451
507
|
|
|
452
508
|
// Custom themes
|
|
453
|
-
import { createAdminStyling } from
|
|
509
|
+
import { createAdminStyling } from "@kyro-cms/core";
|
|
454
510
|
|
|
455
511
|
const myTheme = createAdminStyling({
|
|
456
|
-
primaryColor:
|
|
457
|
-
borderRadius:
|
|
458
|
-
fontFamily:
|
|
512
|
+
primaryColor: "#6366f1",
|
|
513
|
+
borderRadius: "medium",
|
|
514
|
+
fontFamily: "Inter",
|
|
459
515
|
});
|
|
460
516
|
```
|
|
461
517
|
|
|
@@ -463,6 +519,37 @@ const myTheme = createAdminStyling({
|
|
|
463
519
|
|
|
464
520
|
## Deployment
|
|
465
521
|
|
|
522
|
+
### Quick Start with Docker
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
# Start PostgreSQL + Redis
|
|
526
|
+
docker compose up -d
|
|
527
|
+
|
|
528
|
+
# Push schema to database
|
|
529
|
+
npm run db:push
|
|
530
|
+
|
|
531
|
+
# Create admin user
|
|
532
|
+
kyro auth bootstrap -e admin@example.com -p "SecurePass123!"
|
|
533
|
+
|
|
534
|
+
# Start development
|
|
535
|
+
npm run dev
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### Environment Variables Required
|
|
539
|
+
|
|
540
|
+
```bash
|
|
541
|
+
# Database (PostgreSQL)
|
|
542
|
+
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/kyro_cms
|
|
543
|
+
DATABASE_SSL=false
|
|
544
|
+
|
|
545
|
+
# Redis (sessions/cache) - supports Redis Cloud
|
|
546
|
+
REDIS_URL=redis://localhost:6379
|
|
547
|
+
REDIS_TLS=false
|
|
548
|
+
|
|
549
|
+
# JWT (required)
|
|
550
|
+
JWT_SECRET=change-me-in-production-min-32-chars
|
|
551
|
+
```
|
|
552
|
+
|
|
466
553
|
### Vercel
|
|
467
554
|
|
|
468
555
|
```bash
|
|
@@ -470,6 +557,7 @@ vercel --prod
|
|
|
470
557
|
```
|
|
471
558
|
|
|
472
559
|
Environment variables:
|
|
560
|
+
|
|
473
561
|
- `DATABASE_URL` - PostgreSQL connection string
|
|
474
562
|
- `JWT_SECRET` - JWT signing secret
|
|
475
563
|
|
|
@@ -575,6 +663,7 @@ MIT License - see [LICENSE](LICENSE) for details.
|
|
|
575
663
|
## Acknowledgments
|
|
576
664
|
|
|
577
665
|
Built with inspiration from:
|
|
666
|
+
|
|
578
667
|
- [Payload CMS](https://payloadcms.com/) - The headless CMS that pushed the industry forward
|
|
579
668
|
- [Strapi](https://strapi.io/) - Open source headless CMS
|
|
580
669
|
- [Sanity](https://www.sanity.io/) - Real-time content infrastructure
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkI4BORBXT_cjs = require('./chunk-I4BORBXT.cjs');
|
|
4
|
+
require('./chunk-Q7SFCCGT.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, "autoBootstrap", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () { return chunkI4BORBXT_cjs.autoBootstrap; }
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "bootstrapAdmin", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return chunkI4BORBXT_cjs.bootstrapAdmin; }
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(exports, "bootstrapWithRetry", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return chunkI4BORBXT_cjs.bootstrapWithRetry; }
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(exports, "checkBootstrapRequired", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return chunkI4BORBXT_cjs.checkBootstrapRequired; }
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "getBootstrapFromEnv", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () { return chunkI4BORBXT_cjs.getBootstrapFromEnv; }
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=bootstrap-2WJK6PG7.cjs.map
|
|
29
|
+
//# sourceMappingURL=bootstrap-2WJK6PG7.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"bootstrap-2WJK6PG7.cjs"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"bootstrap-Q2TWUQF3.js"}
|