create-nextjs-cms 0.5.16 → 0.5.18
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/package.json +4 -4
- package/templates/default/CHANGELOG.md +21 -0
- package/templates/default/app/api/video/route.ts +2 -2
- package/templates/default/components/CategorySectionSelectInput.tsx +2 -2
- package/templates/default/components/form/helpers/util.ts +1 -1
- package/templates/default/components/form/inputs/SelectFormInput.tsx +2 -1
- package/templates/default/next.config.ts +2 -2
- package/templates/default/package.json +3 -3
- package/templates/default/README.md +0 -45
- package/templates/default/app/dictionaries.ts +0 -14
- package/templates/default/section-tests.ts +0 -92
- package/templates/default/test.ts +0 -77
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-nextjs-cms",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.18",
|
|
4
4
|
"private": false,
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-nextjs-cms": "./dist/index.js"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"glob": "^11.0.3",
|
|
17
17
|
"js-yaml": "^4.1.1",
|
|
18
18
|
"prompts": "^2.4.2",
|
|
19
|
-
"nextjs-cms": "0.5.
|
|
19
|
+
"nextjs-cms": "0.5.18"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/fs-extra": "^11.0.4",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"tsx": "^4.20.6",
|
|
29
29
|
"typescript": "^5.9.2",
|
|
30
30
|
"@lzcms/eslint-config": "0.3.0",
|
|
31
|
-
"@lzcms/
|
|
32
|
-
"@lzcms/
|
|
31
|
+
"@lzcms/prettier-config": "0.1.0",
|
|
32
|
+
"@lzcms/tsconfig": "0.1.0"
|
|
33
33
|
},
|
|
34
34
|
"prettier": "@lzcms/prettier-config",
|
|
35
35
|
"scripts": {
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# cms
|
|
2
2
|
|
|
3
|
+
## 0.5.17
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- nextjs-cms@0.5.17
|
|
9
|
+
|
|
10
|
+
## 0.5.16
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- nextjs-cms@0.5.16
|
|
16
|
+
|
|
17
|
+
## 0.5.15
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
- nextjs-cms@0.5.15
|
|
23
|
+
|
|
3
24
|
## 0.5.14
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
|
@@ -4,7 +4,7 @@ import fs from 'fs'
|
|
|
4
4
|
import { readChunk } from 'read-chunk'
|
|
5
5
|
import { fileTypeFromBuffer } from 'file-type'
|
|
6
6
|
import { SectionFactory } from 'nextjs-cms/core/factories'
|
|
7
|
-
import {
|
|
7
|
+
import type { VideoField } from 'nextjs-cms/core/fields'
|
|
8
8
|
import auth from 'nextjs-cms/auth'
|
|
9
9
|
import { sanitizeFileName, sanitizeFolderOrFileName } from 'nextjs-cms/utils'
|
|
10
10
|
import { streamFile } from 'nextjs-cms/api/helpers'
|
|
@@ -71,7 +71,7 @@ export async function GET(request: NextRequest) {
|
|
|
71
71
|
)
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
const fieldInfo = section.fields.find((field) => field.name === fieldName) as
|
|
74
|
+
const fieldInfo = section.fields.find((field) => field.name === fieldName)?.build() as VideoField
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
77
|
* If field is not found, throw an error
|
|
@@ -42,7 +42,7 @@ export default function CategorySectionSelectInput({
|
|
|
42
42
|
useEffect(() => {
|
|
43
43
|
if (input) {
|
|
44
44
|
setChild(null)
|
|
45
|
-
if (input.depth <= 1) return
|
|
45
|
+
if (input.depth && input.depth <= 1) return
|
|
46
46
|
if (value === undefined) {
|
|
47
47
|
return
|
|
48
48
|
}
|
|
@@ -113,7 +113,7 @@ export default function CategorySectionSelectInput({
|
|
|
113
113
|
setValue(undefined)
|
|
114
114
|
setRandomKey(nanoid())
|
|
115
115
|
}}
|
|
116
|
-
allowRecursiveDelete={input.allowRecursiveDelete}
|
|
116
|
+
allowRecursiveDelete={input.allowRecursiveDelete ?? false}
|
|
117
117
|
/>
|
|
118
118
|
</FormInputElement>
|
|
119
119
|
<div ref={parent}>
|
|
@@ -9,7 +9,7 @@ try {
|
|
|
9
9
|
// Try to import the auto-generated file from root
|
|
10
10
|
// Using dynamic require to handle missing file gracefully
|
|
11
11
|
// @/ alias resolves to the app root directory
|
|
12
|
-
const sectionInfo = require('
|
|
12
|
+
const sectionInfo = require('./_section-hot-reload.ts')
|
|
13
13
|
sectionSchemaLastUpdated = sectionInfo?.sectionSchemaLastUpdated ?? Date.now()
|
|
14
14
|
} catch {
|
|
15
15
|
// If file doesn't exist or can't be loaded, use current timestamp as fallback
|
|
@@ -57,6 +57,7 @@ export default function SelectFormInput({
|
|
|
57
57
|
input.value && Array.isArray(input.value) && input.value[1]
|
|
58
58
|
? input.value.slice(1)
|
|
59
59
|
: undefined,
|
|
60
|
+
defaultValue: input.value?.[0]?.value ?? undefined,
|
|
60
61
|
},
|
|
61
62
|
level: data.level,
|
|
62
63
|
}
|
|
@@ -102,7 +103,7 @@ export default function SelectFormInput({
|
|
|
102
103
|
* If the depth is less than or equal to 1, return
|
|
103
104
|
* If the level is greater than or equal to the depth, return
|
|
104
105
|
*/
|
|
105
|
-
if (depth <= 1 || level >= depth) return
|
|
106
|
+
if (depth && (depth <= 1 || level >= depth)) return
|
|
106
107
|
|
|
107
108
|
setIsLoading(true)
|
|
108
109
|
childrenMutation.mutate({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.0.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "next dev --turbopack",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"nanoid": "^5.1.2",
|
|
83
83
|
"next": "^15.5.5",
|
|
84
84
|
"next-themes": "^0.4.4",
|
|
85
|
-
"nextjs-cms": "0.5.
|
|
85
|
+
"nextjs-cms": "0.5.18",
|
|
86
86
|
"plaiceholder": "^3.0.0",
|
|
87
87
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
|
88
88
|
"qrcode": "^1.5.4",
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"eslint-config-prettier": "^10.0.1",
|
|
123
123
|
"eslint-plugin-prettier": "^5.2.3",
|
|
124
124
|
"hanji": "^0.0.5",
|
|
125
|
-
"nextjs-cms-kit": "0.5.
|
|
125
|
+
"nextjs-cms-kit": "0.5.18",
|
|
126
126
|
"postcss": "^8.5.1",
|
|
127
127
|
"prettier": "3.5.0",
|
|
128
128
|
"tailwindcss": "^3.4.16",
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
This is the official repository for LZCMS
|
|
2
|
-
|
|
3
|
-
LZCMS is an open-source content management system that is designed to be simple and easy to use. It is built with Next.js and Tailwind CSS.
|
|
4
|
-
|
|
5
|
-
## Getting Started
|
|
6
|
-
|
|
7
|
-
First, run the development server:
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm run dev
|
|
11
|
-
# or
|
|
12
|
-
yarn dev
|
|
13
|
-
# or
|
|
14
|
-
pnpm dev
|
|
15
|
-
# or
|
|
16
|
-
bun dev
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
20
|
-
|
|
21
|
-
You can start adding sections to the cms by adding a new file in the `sections` directory. The file should end with `.section.ts` and should export a default object with the following properties:
|
|
22
|
-
|
|
23
|
-
```tsx
|
|
24
|
-
export default {
|
|
25
|
-
name: 'Section Name',
|
|
26
|
-
slug: 'section-name',
|
|
27
|
-
fields: [
|
|
28
|
-
{
|
|
29
|
-
name: 'Field Name',
|
|
30
|
-
slug: 'field-name',
|
|
31
|
-
type: 'text',
|
|
32
|
-
required: true,
|
|
33
|
-
},
|
|
34
|
-
],
|
|
35
|
-
};
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
## Learn More
|
|
40
|
-
|
|
41
|
-
To learn more about LZCMS, take a look at the following documentation:
|
|
42
|
-
|
|
43
|
-
- [LZCMS Documentation](https://lzcms.org/docs) - learn about lzcms features and API.
|
|
44
|
-
|
|
45
|
-
You can check out [the LZCMS GitHub repository](https://github.com/lzcms/lzcms/) - your feedback and contributions are welcome!
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import 'server-only'
|
|
2
|
-
|
|
3
|
-
const dictionaries: Record<string, () => Promise<any>> = {
|
|
4
|
-
en: () => import('@/dictionaries/en.json').then((module) => module.default),
|
|
5
|
-
ar: () => import('@/dictionaries/ar.json').then((module) => module.default),
|
|
6
|
-
// DefaultS to Arabic
|
|
7
|
-
default: () => import('@/dictionaries/ar.json').then((module) => module.default),
|
|
8
|
-
}
|
|
9
|
-
export const getDictionary = async (locale: string) => {
|
|
10
|
-
const dictionary = dictionaries[locale]
|
|
11
|
-
if (dictionary) {
|
|
12
|
-
return dictionary()
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
import { FieldType, SectionInputBuilderBaseConfig, SectionInputBuilderRuntimeConfig } from 'nextjs-cms/core/inputs-builder'
|
|
3
|
-
import { entityKind } from 'nextjs-cms/core/helpers'
|
|
4
|
-
|
|
5
|
-
export interface SectionInputBaseConfig<TInputType extends FieldType>
|
|
6
|
-
extends SectionInputBuilderBaseConfig<TInputType> {
|
|
7
|
-
sectionName: string
|
|
8
|
-
notNull: boolean
|
|
9
|
-
hasDefault: boolean
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type SectionInputTypeConfig<T extends SectionInputBaseConfig<FieldType>, TTypeConfig extends object> = T & {
|
|
13
|
-
brand: 'SectionInput'
|
|
14
|
-
tableName: T['tableName']
|
|
15
|
-
name: T['name']
|
|
16
|
-
dataType: T['dataType']
|
|
17
|
-
columnType: T['columnType']
|
|
18
|
-
data: T['data']
|
|
19
|
-
driverParam: T['driverParam']
|
|
20
|
-
notNull: T['notNull']
|
|
21
|
-
hasDefault: T['hasDefault']
|
|
22
|
-
enumValues: T['enumValues']
|
|
23
|
-
baseColumn: T extends {
|
|
24
|
-
baseColumn: infer U
|
|
25
|
-
}
|
|
26
|
-
? U
|
|
27
|
-
: unknown
|
|
28
|
-
} & TTypeConfig
|
|
29
|
-
|
|
30
|
-
export type InputRuntimeConfig<TData, TRuntimeConfig extends object> = SectionInputBuilderRuntimeConfig<
|
|
31
|
-
TData,
|
|
32
|
-
TRuntimeConfig
|
|
33
|
-
>
|
|
34
|
-
|
|
35
|
-
export declare abstract class SectionInput<
|
|
36
|
-
T extends SectionInputBaseConfig<FieldType> = SectionInputBaseConfig<FieldType>,
|
|
37
|
-
TRuntimeConfig extends object = object,
|
|
38
|
-
TTypeConfig extends object = object,
|
|
39
|
-
> {
|
|
40
|
-
// implements DriverValueMapper<T['data'], T['driverParam']>
|
|
41
|
-
readonly section: Section
|
|
42
|
-
static readonly [entityKind]: string
|
|
43
|
-
readonly _: SectionInputTypeConfig<T, TTypeConfig>
|
|
44
|
-
readonly name: string
|
|
45
|
-
readonly primary: boolean
|
|
46
|
-
readonly notNull: boolean
|
|
47
|
-
// readonly default: T['data'] | SQL | undefined
|
|
48
|
-
// readonly defaultFn: (() => T['data'] | SQL) | undefined
|
|
49
|
-
// readonly onUpdateFn: (() => T['data'] | SQL) | undefined
|
|
50
|
-
readonly hasDefault: boolean
|
|
51
|
-
readonly isUnique: boolean
|
|
52
|
-
readonly uniqueName: string | undefined
|
|
53
|
-
readonly uniqueType: string | undefined
|
|
54
|
-
readonly dataType: T['dataType']
|
|
55
|
-
readonly columnType: T['columnType']
|
|
56
|
-
readonly enumValues: T['enumValues']
|
|
57
|
-
protected config: InputRuntimeConfig<T['data'], TRuntimeConfig>
|
|
58
|
-
constructor(section: Section, config: InputRuntimeConfig<T['data'], TRuntimeConfig>)
|
|
59
|
-
// abstract getSQLType(): string
|
|
60
|
-
// mapFromDriverValue(value: unknown): unknown
|
|
61
|
-
// mapToDriverValue(value: unknown): unknown
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export interface SectionConfigBase<TInput extends SectionInput = SectionInput<any>> {
|
|
65
|
-
name: string
|
|
66
|
-
inputs: Record<string, TInput>
|
|
67
|
-
test?: string
|
|
68
|
-
}
|
|
69
|
-
export type Writable<T> = {
|
|
70
|
-
-readonly [P in keyof T]: T[P]
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export declare class Section<T extends SectionConfigBase = SectionConfigBase> {
|
|
74
|
-
static readonly [entityKind]: string
|
|
75
|
-
readonly name: T['name']
|
|
76
|
-
readonly inputs: T['inputs']
|
|
77
|
-
readonly test: T['test']
|
|
78
|
-
readonly _: {
|
|
79
|
-
readonly brand: 'Section'
|
|
80
|
-
readonly config: T
|
|
81
|
-
readonly name: T['name']
|
|
82
|
-
// readonly schema: T['schema']
|
|
83
|
-
readonly inputs: T['inputs']
|
|
84
|
-
// readonly inferSelect: InferSelectModel<Table<T>>
|
|
85
|
-
// readonly inferInsert: InferInsertModel<Table<T>>
|
|
86
|
-
}
|
|
87
|
-
// readonly $inferSelect: InferSelectModel<Table<T>>
|
|
88
|
-
// readonly $inferInsert: InferInsertModel<Table<T>>;
|
|
89
|
-
// [IsDrizzleTable]: boolean
|
|
90
|
-
constructor(name: string, inputs: T['inputs'])
|
|
91
|
-
}
|
|
92
|
-
*/
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
import { BaseField } from '@/lz/types'
|
|
3
|
-
|
|
4
|
-
type Person = {
|
|
5
|
-
name: string
|
|
6
|
-
job: string
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
type Result<T> = {
|
|
10
|
-
[K in keyof T]: T[K]
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
type ExtraConfig<T> = (inputs: Result<T>) => Person
|
|
14
|
-
|
|
15
|
-
type HasItemsSection<T> = {
|
|
16
|
-
name: string
|
|
17
|
-
car: string
|
|
18
|
-
inputs: Result<T>
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
declare class PrimaryKey {
|
|
22
|
-
private field: BaseField
|
|
23
|
-
constructor(field: BaseField)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Overload signatures
|
|
27
|
-
export function hasItemsSection<T extends Record<string, Person>>(
|
|
28
|
-
section: HasItemsSection<T> & { db: { table: string; setPrimaryKey?: undefined } },
|
|
29
|
-
): { section: HasItemsSection<T> & { db: { table: string } } }
|
|
30
|
-
|
|
31
|
-
export function hasItemsSection<T extends Record<string, Person>>(
|
|
32
|
-
section: HasItemsSection<T> & { db: { table: string; setPrimaryKey?: ExtraConfig<T> } },
|
|
33
|
-
): { section: HasItemsSection<T> & { db: { table: string; primaryKey: Person | null } } }
|
|
34
|
-
|
|
35
|
-
export function hasItemsSection<T extends Record<string, Person>>(
|
|
36
|
-
section: HasItemsSection<T> & { db: { table: string; setPrimaryKey?: ExtraConfig<T> } },
|
|
37
|
-
): {
|
|
38
|
-
section: HasItemsSection<T> & { db: { table: string; primaryKey: Person | null } }
|
|
39
|
-
} {
|
|
40
|
-
let primaryKey = null
|
|
41
|
-
|
|
42
|
-
if (section.db?.setPrimaryKey) {
|
|
43
|
-
primaryKey = section.db.setPrimaryKey(section.inputs)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return {
|
|
47
|
-
section: {
|
|
48
|
-
...section,
|
|
49
|
-
db: {
|
|
50
|
-
...section.db,
|
|
51
|
-
primaryKey: primaryKey,
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const p1: Person = { name: 'Fadi', job: 'dev' }
|
|
58
|
-
const p2: Person = { name: 'Abdo', job: 'dev' }
|
|
59
|
-
|
|
60
|
-
const x = hasItemsSection({
|
|
61
|
-
name: 'asd',
|
|
62
|
-
car: 'asd',
|
|
63
|
-
inputs: {
|
|
64
|
-
fadi: p1,
|
|
65
|
-
abdo: p2,
|
|
66
|
-
},
|
|
67
|
-
db: {
|
|
68
|
-
table: 'asd',
|
|
69
|
-
setPrimaryKey: (inputs) => {
|
|
70
|
-
return inputs.fadi
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
})
|
|
74
|
-
x.section.db.primaryKey
|
|
75
|
-
x.section.db.primaryKey
|
|
76
|
-
// Now `x.section.inputs` will have autocompletion
|
|
77
|
-
*/
|