@xleddyl/nuxt-cms 0.1.34 → 0.1.36
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
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# nuxt-cms
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@xleddyl/nuxt-cms)
|
|
4
|
+
[](https://github.com/xleddyl/nuxt-cms/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
3
7
|
nuxt-cms is a Nuxt module that leverages the Nitro server to ship a lightweight CMS together with your Nuxt frontend, no external CMS, no second service to deploy, nothing extra to pay for. Content lives next to the code that renders it: you define content types in code, editors manage entries from a built-in admin panel, and the same server that serves your site serves your content.
|
|
4
8
|
|
|
5
9
|
- **Zero extra infrastructure**: the CMS runs inside your app's Nitro server; you deploy one thing.
|
|
@@ -8,6 +12,14 @@ nuxt-cms is a Nuxt module that leverages the Nitro server to ship a lightweight
|
|
|
8
12
|
- **Public GraphQL API**: read-only, typed end-to-end via gql.tada, with filtering, sorting and pagination; fields marked `private` stay out of it.
|
|
9
13
|
- **SQLite, Postgres or libSQL/Turso**: a local file database by default, one config line to switch (including remote SQLite over the network).
|
|
10
14
|
|
|
15
|
+
## Screenshots
|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+

|
|
22
|
+
|
|
11
23
|
## Installation
|
|
12
24
|
|
|
13
25
|
```bash
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import { introspectionFromSchema, buildSchema } from 'graphql';
|
|
|
10
10
|
import { minifyIntrospection, outputIntrospectionFile } from 'gql.tada/internal';
|
|
11
11
|
import { createJiti } from 'jiti';
|
|
12
12
|
import { typeName, blockTypeName, blockUnionName, renderGraphqlSdl } from '../dist/runtime/shared/graphql-sdl.js';
|
|
13
|
-
import { isMultiSelect, fieldConditions, isTranslatableField, isTranslatableMediaField, isPrivateField, DEFAULT_MEDIA_MAX_FILE_SIZE } from '../dist/runtime/shared/index.js';
|
|
13
|
+
import { isMultiSelect, fieldConditions, isTranslatableField, isTranslatableMediaField, isRequiredField, isPrivateField, DEFAULT_MEDIA_MAX_FILE_SIZE } from '../dist/runtime/shared/index.js';
|
|
14
14
|
import { scanMediaDirectory, readMediaFileMeta } from '../dist/runtime/server/utils/media-sync.js';
|
|
15
15
|
|
|
16
16
|
async function collectMediaManifest(root) {
|
|
@@ -294,7 +294,7 @@ function columnExpr(key, field, dialect) {
|
|
|
294
294
|
let expr;
|
|
295
295
|
if (isTranslatableField(field)) {
|
|
296
296
|
expr = isTranslatableMediaField(field) ? `text('${col}')` : jsonExpr(col, dialect);
|
|
297
|
-
if (field
|
|
297
|
+
if (isRequiredField(field)) expr += ".notNull()";
|
|
298
298
|
return ` ${key}: ${expr},`;
|
|
299
299
|
}
|
|
300
300
|
switch (field.type) {
|
|
@@ -326,7 +326,7 @@ function columnExpr(key, field, dialect) {
|
|
|
326
326
|
default:
|
|
327
327
|
expr = `text('${col}')`;
|
|
328
328
|
}
|
|
329
|
-
if (field
|
|
329
|
+
if (isRequiredField(field)) expr += ".notNull()";
|
|
330
330
|
return ` ${key}: ${expr},`;
|
|
331
331
|
}
|
|
332
332
|
function isManyToMany(field) {
|
|
@@ -431,7 +431,7 @@ function fieldTsType(config, entryName, key, field) {
|
|
|
431
431
|
if (field.type === "relation") {
|
|
432
432
|
const target = typeName(field.to);
|
|
433
433
|
if (field.cardinality === "many-to-many") return `${target}[]`;
|
|
434
|
-
return field
|
|
434
|
+
return isRequiredField(field) && !config[field.to]?.drafts ? target : `${target} | null`;
|
|
435
435
|
}
|
|
436
436
|
if (field.type === "media") return "CmsMedia | null";
|
|
437
437
|
if (field.type === "select" && field.multiple) {
|
|
@@ -440,11 +440,11 @@ function fieldTsType(config, entryName, key, field) {
|
|
|
440
440
|
}
|
|
441
441
|
if (field.type === "blocks") {
|
|
442
442
|
const union = blockUnionName(entryName, key);
|
|
443
|
-
return field
|
|
443
|
+
return isRequiredField(field) ? `${union}[]` : `${union}[] | null`;
|
|
444
444
|
}
|
|
445
|
-
if (isTranslatableField(field)) return field
|
|
445
|
+
if (isTranslatableField(field)) return isRequiredField(field) ? "string" : "string | null";
|
|
446
446
|
const base = scalarTsType(field);
|
|
447
|
-
return field
|
|
447
|
+
return isRequiredField(field) ? base : `${base} | null`;
|
|
448
448
|
}
|
|
449
449
|
function blockTypesTs(entryName, key, field) {
|
|
450
450
|
const defs = [];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isPrivateField, isTranslatableField } from "./index.js";
|
|
1
|
+
import { isPrivateField, isRequiredField, isTranslatableField } from "./index.js";
|
|
2
2
|
export function typeName(name) {
|
|
3
3
|
return name.replace(/(?:^|_)([a-z0-9])/gi, (_, c) => c.toUpperCase());
|
|
4
4
|
}
|
|
@@ -52,14 +52,14 @@ function fieldSdl(config, entryName, key, field) {
|
|
|
52
52
|
if (field.type === "relation") {
|
|
53
53
|
const target = typeName(field.to);
|
|
54
54
|
if (field.cardinality === "many-to-many") return ` ${key}: [${target}!]!`;
|
|
55
|
-
const nonNull = field
|
|
55
|
+
const nonNull = isRequiredField(field) && !config[field.to]?.drafts;
|
|
56
56
|
return ` ${key}: ${target}${nonNull ? "!" : ""}`;
|
|
57
57
|
}
|
|
58
58
|
if (field.type === "media") return ` ${key}: CmsMedia`;
|
|
59
59
|
if (field.type === "select" && field.multiple) return ` ${key}: [String!]!`;
|
|
60
60
|
if (field.type === "blocks")
|
|
61
|
-
return ` ${key}: [${blockUnionName(entryName, key)}!]${field
|
|
62
|
-
return ` ${key}: ${scalarFor(field)}${field
|
|
61
|
+
return ` ${key}: [${blockUnionName(entryName, key)}!]${isRequiredField(field) ? "!" : ""}`;
|
|
62
|
+
return ` ${key}: ${scalarFor(field)}${isRequiredField(field) ? "!" : ""}`;
|
|
63
63
|
}
|
|
64
64
|
function entrySdl(config, name, entry) {
|
|
65
65
|
const lines = [" id: ID!"];
|
|
@@ -68,6 +68,7 @@ export interface FieldConfig {
|
|
|
68
68
|
showIf?: FieldCondition | FieldCondition[];
|
|
69
69
|
}
|
|
70
70
|
export declare function isPrivateField(field: FieldConfig): boolean;
|
|
71
|
+
export declare function isRequiredField(field: FieldConfig): boolean;
|
|
71
72
|
export declare function fieldConditions(field: FieldConfig): FieldCondition[];
|
|
72
73
|
export declare function isFieldVisible(field: FieldConfig, values: Record<string, unknown> | null | undefined): boolean;
|
|
73
74
|
export declare function isTranslatableField(field: FieldConfig): boolean;
|
|
@@ -64,6 +64,9 @@ export function normalizeMediaFolder(value) {
|
|
|
64
64
|
export function isPrivateField(field) {
|
|
65
65
|
return !!field.private;
|
|
66
66
|
}
|
|
67
|
+
export function isRequiredField(field) {
|
|
68
|
+
return !!field.required && !field.showIf;
|
|
69
|
+
}
|
|
67
70
|
export function fieldConditions(field) {
|
|
68
71
|
if (!field.showIf) return [];
|
|
69
72
|
return Array.isArray(field.showIf) ? field.showIf : [field.showIf];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xleddyl/nuxt-cms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.36",
|
|
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)",
|