@xleddyl/nuxt-cms 0.1.10 → 0.1.11
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 +61 -1
- package/dist/module.d.mts +3 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +14 -7
- package/dist/runtime/server/plugins/migrate-libsql.d.ts +2 -0
- package/dist/runtime/server/plugins/migrate-libsql.js +17 -0
- package/dist/runtime/server/utils/db-libsql.d.ts +7 -0
- package/dist/runtime/server/utils/db-libsql.js +18 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -6,7 +6,67 @@ nuxt-cms is a Nuxt module that leverages the Nitro server to ship a lightweight
|
|
|
6
6
|
- **Content types in code**: a `cms.config.ts` with `defineCmsConfig()` declares collections, single documents, relations, blocks and translatable fields; database schema, migrations and TypeScript types are generated from it.
|
|
7
7
|
- **Admin panel at `/cms`**: entry editing with validation, drafts, media library (S3-compatible storage), single-admin auth from env credentials.
|
|
8
8
|
- **Public GraphQL API**: read-only, typed end-to-end via gql.tada, with filtering, sorting and pagination.
|
|
9
|
-
- **SQLite or
|
|
9
|
+
- **SQLite, Postgres or libSQL/Turso**: a local file database by default, one config line to switch (including remote SQLite over the network).
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @xleddyl/nuxt-cms
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Register the module and configure it under the `cms` key in `nuxt.config.ts`:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
export default defineNuxtConfig({
|
|
21
|
+
modules: ['@xleddyl/nuxt-cms'],
|
|
22
|
+
cms: {
|
|
23
|
+
database: {
|
|
24
|
+
driver: 'sqlite', // 'sqlite' | 'postgres' (with `url`) | 'libsql' (Turso/remote, with `url` + `authToken`)
|
|
25
|
+
path: 'data/cms.db',
|
|
26
|
+
},
|
|
27
|
+
i18n: {
|
|
28
|
+
locales: ['en', 'it'],
|
|
29
|
+
defaultLocale: 'en',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then declare your content types in a `cms.config.ts` at the project root with `defineCmsConfig()`.
|
|
36
|
+
|
|
37
|
+
### Environment variables
|
|
38
|
+
|
|
39
|
+
Every secret maps to runtime config, so it can be set as an env var instead of in `nuxt.config.ts`:
|
|
40
|
+
|
|
41
|
+
| Variable | Required | Purpose |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| `NUXT_CMS_ADMIN_EMAIL` | yes | admin login email |
|
|
44
|
+
| `NUXT_CMS_ADMIN_PASSWORD` | yes | admin login password |
|
|
45
|
+
| `NUXT_SESSION_PASSWORD` | in production | session encryption key (32+ chars) |
|
|
46
|
+
| `NUXT_CMS_DATABASE_URL` | with `postgres` / remote `libsql` | Postgres connection string or libSQL URL |
|
|
47
|
+
| `NUXT_CMS_DATABASE_AUTH_TOKEN` | with remote `libsql` | libSQL/Turso auth token |
|
|
48
|
+
| `NUXT_CMS_MEDIA_ENDPOINT` | for media | S3-compatible endpoint |
|
|
49
|
+
| `NUXT_CMS_MEDIA_REGION` | for media | S3 region (default `auto`) |
|
|
50
|
+
| `NUXT_CMS_MEDIA_BUCKET` | for media | bucket name |
|
|
51
|
+
| `NUXT_CMS_MEDIA_ACCESS_KEY_ID` | for media | S3 access key id |
|
|
52
|
+
| `NUXT_CMS_MEDIA_SECRET_ACCESS_KEY` | for media | S3 secret access key |
|
|
53
|
+
| `NUXT_PUBLIC_CMS_MEDIA_BASE_URL` | for media | public base URL for uploaded files |
|
|
54
|
+
|
|
55
|
+
## Documentation
|
|
56
|
+
|
|
57
|
+
Full documentation lives in [`docs/`](docs/README.md):
|
|
58
|
+
|
|
59
|
+
- [Getting started](docs/getting-started.md) — install, configure, first content type, run.
|
|
60
|
+
- [Configuration](docs/configuration.md) — every `cms.*` option and the `NUXT_CMS_*` env vars.
|
|
61
|
+
- [Database](docs/database.md) — SQLite, Postgres and libSQL/Turso drivers, migrations, studio.
|
|
62
|
+
- [Schema](docs/schema.md) — `defineCmsConfig`, entries, field types, relations, blocks, i18n.
|
|
63
|
+
- [Querying content](docs/querying.md) — GraphQL API, `useCms` / `$cmsQuery`, filters, sorting, pagination.
|
|
64
|
+
- [Admin panel & security](docs/admin.md) — pages, authentication, sessions, admin REST API.
|
|
65
|
+
- [Media](docs/media.md) — S3-compatible storage, upload flow, allowed file types.
|
|
66
|
+
|
|
67
|
+
## LLM guide
|
|
68
|
+
|
|
69
|
+
[llm.txt](llm.txt) is a compact reference meant to be fed to an LLM: schema definition (`cms.config.ts`, field types, relations, blocks, i18n), the `useCms` / `$cmsQuery` composables and the generated GraphQL API (filters, sorting, pagination).
|
|
10
70
|
|
|
11
71
|
## Development
|
|
12
72
|
|
package/dist/module.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
2
|
|
|
3
3
|
type Dialect = 'sqlite' | 'postgres';
|
|
4
|
+
type Driver = Dialect | 'libsql';
|
|
4
5
|
|
|
5
6
|
interface ModuleOptions {
|
|
6
7
|
configPath: string;
|
|
@@ -9,9 +10,10 @@ interface ModuleOptions {
|
|
|
9
10
|
password: string;
|
|
10
11
|
};
|
|
11
12
|
database: {
|
|
12
|
-
driver?:
|
|
13
|
+
driver?: Driver;
|
|
13
14
|
path?: string;
|
|
14
15
|
url?: string;
|
|
16
|
+
authToken?: string;
|
|
15
17
|
};
|
|
16
18
|
media: {
|
|
17
19
|
endpoint: string;
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -424,7 +424,8 @@ const module$1 = defineNuxtModule({
|
|
|
424
424
|
database: {
|
|
425
425
|
driver: "sqlite",
|
|
426
426
|
path: "data/cms.db",
|
|
427
|
-
url: ""
|
|
427
|
+
url: "",
|
|
428
|
+
authToken: ""
|
|
428
429
|
},
|
|
429
430
|
media: {
|
|
430
431
|
endpoint: "",
|
|
@@ -481,7 +482,11 @@ const module$1 = defineNuxtModule({
|
|
|
481
482
|
const schemaTemplate = addTemplate({
|
|
482
483
|
filename: "cms/schema.ts",
|
|
483
484
|
write: true,
|
|
484
|
-
getContents: () => renderSchemaFile(
|
|
485
|
+
getContents: () => renderSchemaFile(
|
|
486
|
+
cmsConfig,
|
|
487
|
+
options.database.driver === "postgres" ? "postgres" : "sqlite",
|
|
488
|
+
resolveImport
|
|
489
|
+
)
|
|
485
490
|
});
|
|
486
491
|
nuxt.options.alias["#cms-tables"] = schemaTemplate.dst;
|
|
487
492
|
addTemplate({
|
|
@@ -555,12 +560,13 @@ const module$1 = defineNuxtModule({
|
|
|
555
560
|
const {
|
|
556
561
|
driver = "sqlite",
|
|
557
562
|
path: dbPath = "data/cms.db",
|
|
558
|
-
url: databaseUrl = ""
|
|
563
|
+
url: databaseUrl = "",
|
|
564
|
+
authToken: databaseAuthToken = ""
|
|
559
565
|
} = options.database;
|
|
560
566
|
nuxt.options.alias["#cms-db"] = resolver.resolve(
|
|
561
|
-
driver === "postgres" ? "./runtime/server/utils/db-postgres" : "./runtime/server/utils/db-sqlite"
|
|
567
|
+
driver === "postgres" ? "./runtime/server/utils/db-postgres" : driver === "libsql" ? "./runtime/server/utils/db-libsql" : "./runtime/server/utils/db-sqlite"
|
|
562
568
|
);
|
|
563
|
-
const dialect = driver === "postgres" ? "postgresql" : "sqlite";
|
|
569
|
+
const dialect = driver === "postgres" ? "postgresql" : driver === "libsql" ? "turso" : "sqlite";
|
|
564
570
|
const resolvedDbPath = isAbsolute(dbPath) ? dbPath : resolve(nuxt.options.rootDir, dbPath);
|
|
565
571
|
const migrationsDir = resolve(nuxt.options.rootDir, `server/db/migrations/${driver}`);
|
|
566
572
|
const relativeSchemaPath = relative(nuxt.options.rootDir, schemaTemplate.dst);
|
|
@@ -574,14 +580,14 @@ const module$1 = defineNuxtModule({
|
|
|
574
580
|
` dialect: '${dialect}',`,
|
|
575
581
|
` schema: '${toPosix(schemaTemplate.dst)}',`,
|
|
576
582
|
` out: '${toPosix(migrationsDir)}',`,
|
|
577
|
-
driver === "postgres" ? ` dbCredentials: { url: process.env.NUXT_CMS_DATABASE_URL ?? '${databaseUrl}' },` : ` dbCredentials: { url: '${toPosix(resolvedDbPath)}' },`,
|
|
583
|
+
driver === "postgres" ? ` dbCredentials: { url: process.env.NUXT_CMS_DATABASE_URL ?? '${databaseUrl}' },` : driver === "libsql" ? ` dbCredentials: { url: process.env.NUXT_CMS_DATABASE_URL ?? '${databaseUrl || `file:${toPosix(resolvedDbPath)}`}', authToken: process.env.NUXT_CMS_DATABASE_AUTH_TOKEN ?? '${databaseAuthToken}' || undefined },` : ` dbCredentials: { url: '${toPosix(resolvedDbPath)}' },`,
|
|
578
584
|
`}`,
|
|
579
585
|
``
|
|
580
586
|
].join("\n")
|
|
581
587
|
});
|
|
582
588
|
addServerPlugin(
|
|
583
589
|
resolver.resolve(
|
|
584
|
-
driver === "postgres" ? "./runtime/server/plugins/migrate-postgres" : "./runtime/server/plugins/migrate-sqlite"
|
|
590
|
+
driver === "postgres" ? "./runtime/server/plugins/migrate-postgres" : driver === "libsql" ? "./runtime/server/plugins/migrate-libsql" : "./runtime/server/plugins/migrate-sqlite"
|
|
585
591
|
)
|
|
586
592
|
);
|
|
587
593
|
if (!nuxt.options.dev) {
|
|
@@ -612,6 +618,7 @@ const module$1 = defineNuxtModule({
|
|
|
612
618
|
adminEmail: options.admin.email,
|
|
613
619
|
adminPassword: options.admin.password,
|
|
614
620
|
databaseUrl,
|
|
621
|
+
databaseAuthToken,
|
|
615
622
|
dbPath: resolvedDbPath,
|
|
616
623
|
migrationsDir,
|
|
617
624
|
...existingConfig,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { migrate } from "drizzle-orm/libsql/migrator";
|
|
3
|
+
import cmsConfig from "#cms-config";
|
|
4
|
+
import { useRuntimeConfig } from "#imports";
|
|
5
|
+
import { useDb } from "../utils/db-libsql.js";
|
|
6
|
+
export default async () => {
|
|
7
|
+
const { migrationsDir } = useRuntimeConfig().cms;
|
|
8
|
+
if (!existsSync(migrationsDir)) {
|
|
9
|
+
if (Object.keys(cmsConfig).length) {
|
|
10
|
+
console.error(
|
|
11
|
+
`[nuxt-cms] Migrations folder not found: ${migrationsDir}. CMS tables may be missing \u2014 run the dev server once and deploy the generated server/db/migrations folder.`
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
await migrate(useDb(), { migrationsFolder: migrationsDir });
|
|
17
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function useDb(): import("drizzle-orm/libsql").LibSQLDatabase<Record<string, unknown>> & {
|
|
2
|
+
$client: import("@libsql/client").Client;
|
|
3
|
+
};
|
|
4
|
+
type Db = ReturnType<typeof useDb>;
|
|
5
|
+
export type CmsDb = Db | Parameters<Parameters<Db['transaction']>[0]>[0];
|
|
6
|
+
export declare function withTransaction<T>(fn: (db: CmsDb) => Promise<T>): Promise<T>;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { mkdirSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { createClient } from "@libsql/client";
|
|
4
|
+
import { drizzle } from "drizzle-orm/libsql";
|
|
5
|
+
import { useRuntimeConfig } from "#imports";
|
|
6
|
+
let _db = null;
|
|
7
|
+
export function useDb() {
|
|
8
|
+
if (!_db) {
|
|
9
|
+
const { databaseUrl, databaseAuthToken, dbPath } = useRuntimeConfig().cms;
|
|
10
|
+
const url = databaseUrl || `file:${dbPath}`;
|
|
11
|
+
if (url.startsWith("file:")) mkdirSync(dirname(dbPath), { recursive: true });
|
|
12
|
+
_db = drizzle(createClient({ url, authToken: databaseAuthToken || void 0 }));
|
|
13
|
+
}
|
|
14
|
+
return _db;
|
|
15
|
+
}
|
|
16
|
+
export function withTransaction(fn) {
|
|
17
|
+
return useDb().transaction((tx) => fn(tx));
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xleddyl/nuxt-cms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Lightweight CMS that ships with your Nuxt app: runs on the Nitro server, content types defined in code, /cms admin panel, GraphQL API, SQLite or Postgres. No external CMS needed!",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Edoardo Alberti (https://github.com/xleddyl)",
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"headless-cms",
|
|
21
21
|
"self-hosted",
|
|
22
22
|
"sqlite",
|
|
23
|
+
"libsql",
|
|
24
|
+
"turso",
|
|
23
25
|
"postgres",
|
|
24
26
|
"drizzle",
|
|
25
27
|
"graphql"
|
|
@@ -50,6 +52,7 @@
|
|
|
50
52
|
"dist"
|
|
51
53
|
],
|
|
52
54
|
"dependencies": {
|
|
55
|
+
"@libsql/client": "^0.17.4",
|
|
53
56
|
"@nuxt/kit": "^4.4.8",
|
|
54
57
|
"@nuxt/ui": "^4.0.0",
|
|
55
58
|
"@nuxtjs/i18n": "^10.4.0",
|