@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 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 Postgres**: a local file database by default, one config line to switch.
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?: Dialect;
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xleddyl/nuxt-cms",
3
3
  "configKey": "cms",
4
- "version": "0.1.10",
4
+ "version": "0.1.11",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
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(cmsConfig, options.database.driver ?? "sqlite", resolveImport)
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,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -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.10",
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",