@kidecms/core 0.1.7 → 0.1.9
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/admin/components/DocumentActions.tsx +7 -1
- package/admin/components/FieldControl.astro +211 -248
- package/admin/components/RichTextEditor.tsx +2 -2
- package/admin/layouts/AdminLayout.astro +58 -24
- package/dist/admin.d.ts +33 -0
- package/dist/ai.d.ts +15 -0
- package/dist/api.d.ts +14 -0
- package/dist/assets.d.ts +51 -0
- package/dist/auth.d.ts +30 -0
- package/dist/content.d.ts +3 -0
- package/dist/create-admin.d.ts +5 -0
- package/dist/define.d.ts +254 -0
- package/dist/generator.d.ts +9 -0
- package/dist/image.d.ts +9 -0
- package/dist/index.d.ts +28 -0
- package/dist/integration.d.ts +14 -0
- package/dist/integration.js +16 -4
- package/dist/locks.d.ts +7 -0
- package/dist/richtext.d.ts +1 -0
- package/dist/runtime.d.ts +24 -0
- package/dist/schema.d.ts +17 -0
- package/dist/seed.d.ts +2 -0
- package/dist/values.d.ts +8 -0
- package/dist/webhooks.d.ts +2 -0
- package/dist/webhooks.js +3 -1
- package/package.json +1 -1
- package/routes/pages/admin/[...path].astro +4 -1
- package/routes/pages/admin/assets/index.astro +6 -1
package/dist/admin.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { CMSConfig, CollectionConfig, FieldConfig } from "./define";
|
|
2
|
+
export declare const initDateFormat: (config: CMSConfig, nextTimeZone?: string) => void;
|
|
3
|
+
export declare const formatDate: (value: unknown) => string;
|
|
4
|
+
export type AdminRoute = {
|
|
5
|
+
kind: "dashboard";
|
|
6
|
+
} | {
|
|
7
|
+
kind: "recent";
|
|
8
|
+
} | {
|
|
9
|
+
kind: "singles";
|
|
10
|
+
} | {
|
|
11
|
+
kind: "list";
|
|
12
|
+
collectionSlug: string;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "new";
|
|
15
|
+
collectionSlug: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "edit";
|
|
18
|
+
collectionSlug: string;
|
|
19
|
+
documentId: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const resolveAdminRoute: (path: string | undefined) => AdminRoute;
|
|
22
|
+
export declare const humanize: (value: string) => string;
|
|
23
|
+
export declare const formatFieldValue: (field: FieldConfig | undefined, value: unknown, relationLabels?: Record<string, string>) => string;
|
|
24
|
+
export declare const getListColumns: (collection: CollectionConfig, viewConfig?: {
|
|
25
|
+
columns?: string[];
|
|
26
|
+
}) => string[];
|
|
27
|
+
export declare const getFieldSets: (collection: CollectionConfig) => ({
|
|
28
|
+
fields: string[];
|
|
29
|
+
position: "content";
|
|
30
|
+
} | {
|
|
31
|
+
fields: string[];
|
|
32
|
+
position: "sidebar";
|
|
33
|
+
})[];
|
package/dist/ai.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare function isAiEnabled(): boolean;
|
|
2
|
+
export declare function getAiModel(): Promise<any>;
|
|
3
|
+
export declare function streamAltText(imageUrl: string, filename: string): Promise<any>;
|
|
4
|
+
export declare function streamSeoDescription(content: {
|
|
5
|
+
title: string;
|
|
6
|
+
excerpt?: string;
|
|
7
|
+
body?: string;
|
|
8
|
+
}): Promise<any>;
|
|
9
|
+
export declare function streamTranslation(content: {
|
|
10
|
+
text: string;
|
|
11
|
+
sourceLocale: string;
|
|
12
|
+
targetLocale: string;
|
|
13
|
+
fieldName: string;
|
|
14
|
+
fieldType: "text" | "richText" | "slug";
|
|
15
|
+
}): Promise<any>;
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CMSConfig } from "./define";
|
|
2
|
+
export type FindOptions = {
|
|
3
|
+
where?: Record<string, unknown>;
|
|
4
|
+
sort?: {
|
|
5
|
+
field: string;
|
|
6
|
+
direction: "asc" | "desc";
|
|
7
|
+
};
|
|
8
|
+
limit?: number;
|
|
9
|
+
offset?: number;
|
|
10
|
+
status?: "draft" | "published" | "scheduled" | "any";
|
|
11
|
+
locale?: string;
|
|
12
|
+
search?: string;
|
|
13
|
+
};
|
|
14
|
+
export declare const createCms: (config: CMSConfig) => any;
|
package/dist/assets.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export type AssetRecord = {
|
|
2
|
+
_id: string;
|
|
3
|
+
filename: string;
|
|
4
|
+
mimeType: string;
|
|
5
|
+
size: number;
|
|
6
|
+
width: number | null;
|
|
7
|
+
height: number | null;
|
|
8
|
+
focalX: number | null;
|
|
9
|
+
focalY: number | null;
|
|
10
|
+
alt: string | null;
|
|
11
|
+
folder: string | null;
|
|
12
|
+
storagePath: string;
|
|
13
|
+
url: string;
|
|
14
|
+
_createdAt: string;
|
|
15
|
+
};
|
|
16
|
+
export type FolderRecord = {
|
|
17
|
+
_id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
parent: string | null;
|
|
20
|
+
_createdAt: string;
|
|
21
|
+
};
|
|
22
|
+
export declare const assets: {
|
|
23
|
+
upload(file: File, options?: {
|
|
24
|
+
alt?: string;
|
|
25
|
+
folder?: string;
|
|
26
|
+
}): Promise<AssetRecord>;
|
|
27
|
+
find(options?: {
|
|
28
|
+
limit?: number;
|
|
29
|
+
offset?: number;
|
|
30
|
+
folder?: string | null;
|
|
31
|
+
}): Promise<AssetRecord[]>;
|
|
32
|
+
findById(id: string): Promise<AssetRecord | null>;
|
|
33
|
+
findByUrl(url: string): Promise<AssetRecord | null>;
|
|
34
|
+
delete(id: string): Promise<void>;
|
|
35
|
+
update(id: string, data: {
|
|
36
|
+
alt?: string;
|
|
37
|
+
filename?: string;
|
|
38
|
+
folder?: string | null;
|
|
39
|
+
focalX?: number | null;
|
|
40
|
+
focalY?: number | null;
|
|
41
|
+
}): Promise<AssetRecord | null>;
|
|
42
|
+
count(): Promise<number>;
|
|
43
|
+
};
|
|
44
|
+
export declare const folders: {
|
|
45
|
+
create(name: string, parent?: string | null): Promise<FolderRecord>;
|
|
46
|
+
findByParent(parent: string | null): Promise<FolderRecord[]>;
|
|
47
|
+
findById(id: string): Promise<FolderRecord | null>;
|
|
48
|
+
findAll(): Promise<FolderRecord[]>;
|
|
49
|
+
rename(id: string, name: string): Promise<FolderRecord | null>;
|
|
50
|
+
delete(id: string): Promise<void>;
|
|
51
|
+
};
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare const hashPassword: (plain: string) => Promise<string>;
|
|
2
|
+
export declare const verifyPassword: (hash: string, plain: string) => Promise<boolean>;
|
|
3
|
+
export declare const createSession: (userId: string) => Promise<{
|
|
4
|
+
token: string;
|
|
5
|
+
expiresAt: string;
|
|
6
|
+
}>;
|
|
7
|
+
export declare const validateSession: (token: string) => Promise<{
|
|
8
|
+
userId: string;
|
|
9
|
+
expiresAt: string;
|
|
10
|
+
} | null>;
|
|
11
|
+
export declare const destroySession: (token: string) => Promise<void>;
|
|
12
|
+
export type SessionUser = {
|
|
13
|
+
id: string;
|
|
14
|
+
email: string;
|
|
15
|
+
name: string;
|
|
16
|
+
role: string;
|
|
17
|
+
};
|
|
18
|
+
export declare const getSessionUser: (request: Request) => Promise<SessionUser | null>;
|
|
19
|
+
export declare const createInvite: (userId: string) => Promise<{
|
|
20
|
+
token: string;
|
|
21
|
+
expiresAt: string;
|
|
22
|
+
}>;
|
|
23
|
+
export declare const validateInvite: (token: string) => Promise<{
|
|
24
|
+
userId: string;
|
|
25
|
+
expiresAt: string;
|
|
26
|
+
} | null>;
|
|
27
|
+
export declare const consumeInvite: (token: string) => Promise<void>;
|
|
28
|
+
export declare const SESSION_COOKIE_NAME = "cms_session";
|
|
29
|
+
export declare const setSessionCookie: (token: string, expiresAt: string) => string;
|
|
30
|
+
export declare const clearSessionCookie: () => string;
|
package/dist/define.d.ts
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
export type CollectionLabels = {
|
|
2
|
+
singular: string;
|
|
3
|
+
plural: string;
|
|
4
|
+
};
|
|
5
|
+
export type DatabaseConfig = {
|
|
6
|
+
dialect: "sqlite" | "postgres";
|
|
7
|
+
url?: string;
|
|
8
|
+
};
|
|
9
|
+
export type LocaleConfig = {
|
|
10
|
+
default: string;
|
|
11
|
+
supported: string[];
|
|
12
|
+
};
|
|
13
|
+
export type AdminFieldComponent = {
|
|
14
|
+
component?: string;
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
position?: "content" | "sidebar";
|
|
17
|
+
rows?: number;
|
|
18
|
+
help?: string;
|
|
19
|
+
hidden?: boolean;
|
|
20
|
+
};
|
|
21
|
+
export type FieldCondition = {
|
|
22
|
+
field: string;
|
|
23
|
+
value: string | string[] | boolean;
|
|
24
|
+
};
|
|
25
|
+
type BaseFieldConfig<TType extends string, TValue = unknown> = {
|
|
26
|
+
type: TType;
|
|
27
|
+
label?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
required?: boolean;
|
|
30
|
+
defaultValue?: TValue;
|
|
31
|
+
indexed?: boolean;
|
|
32
|
+
unique?: boolean;
|
|
33
|
+
translatable?: boolean;
|
|
34
|
+
condition?: FieldCondition;
|
|
35
|
+
admin?: AdminFieldComponent;
|
|
36
|
+
access?: {
|
|
37
|
+
read?: (context: {
|
|
38
|
+
user?: {
|
|
39
|
+
id: string;
|
|
40
|
+
role?: string;
|
|
41
|
+
email?: string;
|
|
42
|
+
} | null;
|
|
43
|
+
doc?: Record<string, unknown> | null;
|
|
44
|
+
operation: string;
|
|
45
|
+
collection: string;
|
|
46
|
+
}) => boolean | Promise<boolean>;
|
|
47
|
+
update?: (context: {
|
|
48
|
+
user?: {
|
|
49
|
+
id: string;
|
|
50
|
+
role?: string;
|
|
51
|
+
email?: string;
|
|
52
|
+
} | null;
|
|
53
|
+
doc?: Record<string, unknown> | null;
|
|
54
|
+
operation: string;
|
|
55
|
+
collection: string;
|
|
56
|
+
}) => boolean | Promise<boolean>;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export type TextFieldConfig = BaseFieldConfig<"text", string> & {
|
|
60
|
+
maxLength?: number;
|
|
61
|
+
};
|
|
62
|
+
export type SlugFieldConfig = BaseFieldConfig<"slug", string> & {
|
|
63
|
+
from?: string;
|
|
64
|
+
};
|
|
65
|
+
export type EmailFieldConfig = BaseFieldConfig<"email", string>;
|
|
66
|
+
export type NumberFieldConfig = BaseFieldConfig<"number", number>;
|
|
67
|
+
export type BooleanFieldConfig = BaseFieldConfig<"boolean", boolean>;
|
|
68
|
+
export type DateFieldConfig = BaseFieldConfig<"date", string>;
|
|
69
|
+
export type SelectFieldConfig = BaseFieldConfig<"select", string> & {
|
|
70
|
+
options: string[];
|
|
71
|
+
};
|
|
72
|
+
export type RichTextNode = {
|
|
73
|
+
type: string;
|
|
74
|
+
value?: string;
|
|
75
|
+
level?: number;
|
|
76
|
+
children?: RichTextNode[];
|
|
77
|
+
[key: string]: unknown;
|
|
78
|
+
};
|
|
79
|
+
export type RichTextDocument = {
|
|
80
|
+
type: "root";
|
|
81
|
+
children: RichTextNode[];
|
|
82
|
+
};
|
|
83
|
+
export type RichTextFieldConfig = BaseFieldConfig<"richText", RichTextDocument>;
|
|
84
|
+
export type ImageFieldConfig = BaseFieldConfig<"image", string>;
|
|
85
|
+
export type RelationFieldConfig = BaseFieldConfig<"relation", string | string[]> & {
|
|
86
|
+
collection: string;
|
|
87
|
+
hasMany?: boolean;
|
|
88
|
+
};
|
|
89
|
+
export type ArrayFieldConfig = BaseFieldConfig<"array", unknown[]> & {
|
|
90
|
+
of: FieldConfig;
|
|
91
|
+
};
|
|
92
|
+
export type JsonFieldConfig = BaseFieldConfig<"json", unknown> & {
|
|
93
|
+
schema?: string;
|
|
94
|
+
};
|
|
95
|
+
export type BlocksFieldConfig = BaseFieldConfig<"blocks", Array<Record<string, unknown>>> & {
|
|
96
|
+
types: Record<string, Record<string, FieldConfig>>;
|
|
97
|
+
};
|
|
98
|
+
export type FieldConfig = TextFieldConfig | SlugFieldConfig | EmailFieldConfig | NumberFieldConfig | BooleanFieldConfig | DateFieldConfig | SelectFieldConfig | RichTextFieldConfig | ImageFieldConfig | RelationFieldConfig | ArrayFieldConfig | JsonFieldConfig | BlocksFieldConfig;
|
|
99
|
+
export type CollectionFieldMap = Record<string, FieldConfig>;
|
|
100
|
+
export type SeedDocument = Record<string, unknown>;
|
|
101
|
+
export type CollectionViewConfig = {
|
|
102
|
+
list?: {
|
|
103
|
+
columns?: string[];
|
|
104
|
+
defaultSort?: {
|
|
105
|
+
field: string;
|
|
106
|
+
direction: "asc" | "desc";
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
export type CollectionConfig = {
|
|
111
|
+
slug: string;
|
|
112
|
+
labels: CollectionLabels;
|
|
113
|
+
labelField?: string;
|
|
114
|
+
pathPrefix?: string;
|
|
115
|
+
preview?: boolean | string;
|
|
116
|
+
timestamps?: boolean;
|
|
117
|
+
drafts?: boolean;
|
|
118
|
+
versions?: {
|
|
119
|
+
max: number;
|
|
120
|
+
};
|
|
121
|
+
auth?: boolean;
|
|
122
|
+
singleton?: boolean;
|
|
123
|
+
access?: CollectionAccess;
|
|
124
|
+
hooks?: CollectionHooks;
|
|
125
|
+
fields: CollectionFieldMap;
|
|
126
|
+
views?: CollectionViewConfig;
|
|
127
|
+
seed?: SeedDocument[];
|
|
128
|
+
};
|
|
129
|
+
export type AdminNavItem = {
|
|
130
|
+
label: string;
|
|
131
|
+
href: string;
|
|
132
|
+
icon?: string;
|
|
133
|
+
/** Sort order — lower values appear first (default: 0) */
|
|
134
|
+
weight?: number;
|
|
135
|
+
};
|
|
136
|
+
export type WebhookEvent = "create" | "update" | "delete" | "publish" | "unpublish";
|
|
137
|
+
export type WebhookContext = {
|
|
138
|
+
user?: {
|
|
139
|
+
id: string;
|
|
140
|
+
role?: string;
|
|
141
|
+
email?: string;
|
|
142
|
+
} | null;
|
|
143
|
+
event: WebhookEvent;
|
|
144
|
+
collection: string;
|
|
145
|
+
timestamp: string;
|
|
146
|
+
};
|
|
147
|
+
export type WebhookConfig = {
|
|
148
|
+
/** Display name (shown in logs) */
|
|
149
|
+
name: string;
|
|
150
|
+
/** URL to POST to */
|
|
151
|
+
url: string;
|
|
152
|
+
/** Events that trigger this webhook */
|
|
153
|
+
events: WebhookEvent[];
|
|
154
|
+
/** Restrict to specific collections (omit for all) */
|
|
155
|
+
collections?: string[];
|
|
156
|
+
/** HTTP method (default: POST) */
|
|
157
|
+
method?: "POST" | "PUT" | "PATCH";
|
|
158
|
+
/** Custom headers */
|
|
159
|
+
headers?: Record<string, string>;
|
|
160
|
+
/** Transform the payload (default: { event, collection, doc, user, timestamp }) */
|
|
161
|
+
payload?: (doc: Record<string, unknown>, context: WebhookContext) => any;
|
|
162
|
+
};
|
|
163
|
+
export type AdminUploadConfig = {
|
|
164
|
+
/** Allowed MIME types (default: images, PDF, video) */
|
|
165
|
+
allowedTypes?: string[];
|
|
166
|
+
/** Max file size in bytes (default: 50 MB) */
|
|
167
|
+
maxFileSize?: number;
|
|
168
|
+
};
|
|
169
|
+
export type AdminRateLimitConfig = {
|
|
170
|
+
/** Max login attempts before blocking (default: 5) */
|
|
171
|
+
maxAttempts?: number;
|
|
172
|
+
/** Time window in milliseconds (default: 15 minutes) */
|
|
173
|
+
windowMs?: number;
|
|
174
|
+
};
|
|
175
|
+
export type AdminConfig = {
|
|
176
|
+
dateFormat?: string;
|
|
177
|
+
nav?: AdminNavItem[];
|
|
178
|
+
uploads?: AdminUploadConfig;
|
|
179
|
+
rateLimit?: AdminRateLimitConfig;
|
|
180
|
+
/** Admin list page size (default: 20) */
|
|
181
|
+
pageSize?: number;
|
|
182
|
+
/** Webhooks fired on content events */
|
|
183
|
+
webhooks?: WebhookConfig[];
|
|
184
|
+
};
|
|
185
|
+
export type CMSConfig = {
|
|
186
|
+
database?: DatabaseConfig;
|
|
187
|
+
locales?: LocaleConfig;
|
|
188
|
+
admin?: AdminConfig;
|
|
189
|
+
collections: CollectionConfig[];
|
|
190
|
+
};
|
|
191
|
+
export type AccessContext = {
|
|
192
|
+
user?: {
|
|
193
|
+
id: string;
|
|
194
|
+
role?: string;
|
|
195
|
+
email?: string;
|
|
196
|
+
} | null;
|
|
197
|
+
doc?: Record<string, unknown> | null;
|
|
198
|
+
operation: string;
|
|
199
|
+
collection: string;
|
|
200
|
+
};
|
|
201
|
+
export type AccessRule = (context: AccessContext) => boolean | Promise<boolean>;
|
|
202
|
+
export type CollectionAccess = Partial<Record<"read" | "create" | "update" | "delete" | "publish" | "schedule", AccessRule>>;
|
|
203
|
+
export declare const hasRole: (...roles: string[]) => AccessRule;
|
|
204
|
+
export type HookContext = {
|
|
205
|
+
user?: AccessContext["user"];
|
|
206
|
+
operation: string;
|
|
207
|
+
collection: string;
|
|
208
|
+
timestamp: string;
|
|
209
|
+
cache?: {
|
|
210
|
+
invalidate: (opts: {
|
|
211
|
+
tags: string[];
|
|
212
|
+
}) => void;
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
export type CollectionHooks = {
|
|
216
|
+
beforeCreate?: (data: Record<string, unknown>, context: HookContext) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
217
|
+
afterCreate?: (doc: Record<string, unknown>, context: HookContext) => void | Promise<void>;
|
|
218
|
+
beforeUpdate?: (data: Record<string, unknown>, existing: Record<string, unknown>, context: HookContext) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
219
|
+
afterUpdate?: (doc: Record<string, unknown>, context: HookContext) => void | Promise<void>;
|
|
220
|
+
beforeDelete?: (doc: Record<string, unknown>, context: HookContext) => void | Promise<void>;
|
|
221
|
+
afterDelete?: (doc: Record<string, unknown>, context: HookContext) => void | Promise<void>;
|
|
222
|
+
beforePublish?: (doc: Record<string, unknown>, context: HookContext) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
223
|
+
afterPublish?: (doc: Record<string, unknown>, context: HookContext) => void | Promise<void>;
|
|
224
|
+
beforeUnpublish?: (doc: Record<string, unknown>, context: HookContext) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
225
|
+
afterUnpublish?: (doc: Record<string, unknown>, context: HookContext) => void | Promise<void>;
|
|
226
|
+
beforeSchedule?: (doc: Record<string, unknown>, context: HookContext) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
227
|
+
afterSchedule?: (doc: Record<string, unknown>, context: HookContext) => void | Promise<void>;
|
|
228
|
+
};
|
|
229
|
+
export declare const fields: {
|
|
230
|
+
text: (options?: Omit<TextFieldConfig, "type">) => TextFieldConfig;
|
|
231
|
+
slug: (options?: Omit<SlugFieldConfig, "type">) => SlugFieldConfig;
|
|
232
|
+
email: (options?: Omit<EmailFieldConfig, "type">) => EmailFieldConfig;
|
|
233
|
+
number: (options?: Omit<NumberFieldConfig, "type">) => NumberFieldConfig;
|
|
234
|
+
boolean: (options?: Omit<BooleanFieldConfig, "type">) => BooleanFieldConfig;
|
|
235
|
+
date: (options?: Omit<DateFieldConfig, "type">) => DateFieldConfig;
|
|
236
|
+
select: (options: Omit<SelectFieldConfig, "type">) => SelectFieldConfig;
|
|
237
|
+
richText: (options?: Omit<RichTextFieldConfig, "type">) => RichTextFieldConfig;
|
|
238
|
+
image: (options?: Omit<ImageFieldConfig, "type">) => ImageFieldConfig;
|
|
239
|
+
relation: (options: Omit<RelationFieldConfig, "type">) => RelationFieldConfig;
|
|
240
|
+
array: (options: Omit<ArrayFieldConfig, "type">) => ArrayFieldConfig;
|
|
241
|
+
json: (options?: Omit<JsonFieldConfig, "type">) => JsonFieldConfig;
|
|
242
|
+
blocks: (options: Omit<BlocksFieldConfig, "type">) => BlocksFieldConfig;
|
|
243
|
+
};
|
|
244
|
+
export declare const defineCollection: (collection: CollectionConfig) => CollectionConfig;
|
|
245
|
+
export declare const defineConfig: (config: CMSConfig) => CMSConfig;
|
|
246
|
+
export declare const getCollectionMap: (config: CMSConfig) => {
|
|
247
|
+
[k: string]: CollectionConfig;
|
|
248
|
+
};
|
|
249
|
+
export declare const getDefaultLocale: (config: CMSConfig) => string;
|
|
250
|
+
export declare const getTranslatableFieldNames: (collection: CollectionConfig) => string[];
|
|
251
|
+
export declare const isStructuralField: (field: FieldConfig) => boolean;
|
|
252
|
+
export declare const getCollectionLabel: (collection: CollectionConfig) => string;
|
|
253
|
+
export declare const getLabelField: (collection: CollectionConfig) => string;
|
|
254
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CMSConfig } from "./define";
|
|
2
|
+
type GeneratorOptions = {
|
|
3
|
+
outputDir: string;
|
|
4
|
+
coreImportPath?: string;
|
|
5
|
+
runtimeImportPath?: string;
|
|
6
|
+
configImportPath?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const generate: (config: CMSConfig, options: GeneratorOptions) => Promise<void>;
|
|
9
|
+
export {};
|
package/dist/image.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const ALLOWED_FORMATS: readonly ["webp", "avif", "jpeg", "png"];
|
|
2
|
+
type Format = (typeof ALLOWED_FORMATS)[number];
|
|
3
|
+
export declare function cmsImage(src: string, width?: number, format?: Format): string;
|
|
4
|
+
export declare function cmsSrcset(src: string, widths?: number[], format?: Format): string;
|
|
5
|
+
export declare function transformImage(src: string, width?: number, format?: string, quality?: number): Promise<{
|
|
6
|
+
buffer: Buffer;
|
|
7
|
+
contentType: string;
|
|
8
|
+
} | null>;
|
|
9
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export { configureCmsRuntime, resetCmsRuntime, getCmsRuntime, getDb, closeDb, getStorage, getEmail, readEnv, } from "./runtime";
|
|
2
|
+
export type { CmsRuntimeConfig, CmsStorageAdapter, CmsEmailAdapter } from "./runtime";
|
|
3
|
+
export { initSchema, getSchema, resetSchema } from "./schema";
|
|
4
|
+
export { fields, defineCollection, defineConfig, getCollectionMap, getDefaultLocale, getTranslatableFieldNames, isStructuralField, getCollectionLabel, getLabelField, hasRole, } from "./define";
|
|
5
|
+
export type { CMSConfig, CollectionConfig, CollectionFieldMap, FieldConfig, TextFieldConfig, SlugFieldConfig, EmailFieldConfig, NumberFieldConfig, BooleanFieldConfig, DateFieldConfig, SelectFieldConfig, RichTextFieldConfig, ImageFieldConfig, RelationFieldConfig, ArrayFieldConfig, JsonFieldConfig, BlocksFieldConfig, RichTextNode, RichTextDocument, CollectionLabels, DatabaseConfig, LocaleConfig, AdminConfig, AdminNavItem, WebhookConfig, WebhookEvent, WebhookContext, AdminFieldComponent, FieldCondition, SeedDocument, CollectionViewConfig, AccessContext, AccessRule, CollectionAccess, HookContext, CollectionHooks, } from "./define";
|
|
6
|
+
export { createCms } from "./api";
|
|
7
|
+
export type { FindOptions } from "./api";
|
|
8
|
+
export type CustomFieldProps = {
|
|
9
|
+
name: string;
|
|
10
|
+
field: import("./define").FieldConfig;
|
|
11
|
+
value: string;
|
|
12
|
+
readOnly: boolean;
|
|
13
|
+
};
|
|
14
|
+
export { hashPassword, verifyPassword, createSession, validateSession, destroySession, getSessionUser, createInvite, validateInvite, consumeInvite, SESSION_COOKIE_NAME, setSessionCookie, clearSessionCookie, } from "./auth";
|
|
15
|
+
export type { SessionUser } from "./auth";
|
|
16
|
+
export { assets, folders } from "./assets";
|
|
17
|
+
export type { AssetRecord, FolderRecord } from "./assets";
|
|
18
|
+
export { parseBlocks, parseList, cacheTags } from "./content";
|
|
19
|
+
export { renderRichText, createRichTextFromPlainText, richTextToPlainText } from "./richtext";
|
|
20
|
+
export { cloneValue, slugify, escapeHtml, serializeFieldValue } from "./values";
|
|
21
|
+
export { cmsImage, cmsSrcset, transformImage } from "./image";
|
|
22
|
+
export { initDateFormat, formatDate, resolveAdminRoute, humanize, formatFieldValue, getListColumns, getFieldSets, } from "./admin";
|
|
23
|
+
export type { AdminRoute } from "./admin";
|
|
24
|
+
export { acquireLock, releaseLock } from "./locks";
|
|
25
|
+
export { isAiEnabled, getAiModel, streamAltText, streamSeoDescription, streamTranslation } from "./ai";
|
|
26
|
+
export { generate } from "./generator";
|
|
27
|
+
export { seedDatabase } from "./seed";
|
|
28
|
+
export { createAdminUser } from "./create-admin";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AstroIntegration } from "astro";
|
|
2
|
+
export interface CmsIntegrationOptions {
|
|
3
|
+
/** Path to the CMS config file (default: "src/cms/cms.config") */
|
|
4
|
+
configPath?: string;
|
|
5
|
+
/** Path to the CMS runtime file (default: "src/cms/runtime") */
|
|
6
|
+
runtimePath?: string;
|
|
7
|
+
/** Path to the generated output directory (default: "src/cms/.generated") */
|
|
8
|
+
generatedPath?: string;
|
|
9
|
+
/** Path to the adapters directory (default: "src/cms/adapters") */
|
|
10
|
+
adaptersPath?: string;
|
|
11
|
+
/** Path to the generator script (default: "src/cms/generator.ts") */
|
|
12
|
+
generatorPath?: string;
|
|
13
|
+
}
|
|
14
|
+
export default function cmsIntegration(options?: CmsIntegrationOptions): AstroIntegration;
|
package/dist/integration.js
CHANGED
|
@@ -64,7 +64,7 @@ export default function cmsIntegration(options) {
|
|
|
64
64
|
return {
|
|
65
65
|
name: "kide-cms",
|
|
66
66
|
hooks: {
|
|
67
|
-
"astro:config:setup": ({ command, updateConfig, injectRoute, addMiddleware }) => {
|
|
67
|
+
"astro:config:setup": ({ command, updateConfig, injectRoute, injectScript, addMiddleware }) => {
|
|
68
68
|
const root = process.cwd();
|
|
69
69
|
// Generate a wrapper CSS that adds @source directives and imports user's admin CSS
|
|
70
70
|
const corePkgDir = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
|
@@ -193,7 +193,10 @@ export default function cmsIntegration(options) {
|
|
|
193
193
|
injectRoute({ pattern: "/admin/setup", entrypoint: "@kidecms/core/routes/pages/admin/setup.astro" });
|
|
194
194
|
injectRoute({ pattern: "/admin/invite", entrypoint: "@kidecms/core/routes/pages/admin/invite.astro" });
|
|
195
195
|
injectRoute({ pattern: "/admin/assets", entrypoint: "@kidecms/core/routes/pages/admin/assets/index.astro" });
|
|
196
|
-
injectRoute({
|
|
196
|
+
injectRoute({
|
|
197
|
+
pattern: "/admin/assets/[id]",
|
|
198
|
+
entrypoint: "@kidecms/core/routes/pages/admin/assets/[id].astro",
|
|
199
|
+
});
|
|
197
200
|
injectRoute({ pattern: "/admin/[...path]", entrypoint: "@kidecms/core/routes/pages/admin/[...path].astro" });
|
|
198
201
|
// Inject API routes
|
|
199
202
|
injectRoute({ pattern: "/api/cms/auth/login", entrypoint: "@kidecms/core/routes/api/cms/auth/login.ts" });
|
|
@@ -201,7 +204,10 @@ export default function cmsIntegration(options) {
|
|
|
201
204
|
injectRoute({ pattern: "/api/cms/auth/setup", entrypoint: "@kidecms/core/routes/api/cms/auth/setup.ts" });
|
|
202
205
|
injectRoute({ pattern: "/api/cms/auth/invite", entrypoint: "@kidecms/core/routes/api/cms/auth/invite.ts" });
|
|
203
206
|
injectRoute({ pattern: "/api/cms/assets/upload", entrypoint: "@kidecms/core/routes/api/cms/assets/upload.ts" });
|
|
204
|
-
injectRoute({
|
|
207
|
+
injectRoute({
|
|
208
|
+
pattern: "/api/cms/assets/folders",
|
|
209
|
+
entrypoint: "@kidecms/core/routes/api/cms/assets/folders.ts",
|
|
210
|
+
});
|
|
205
211
|
injectRoute({ pattern: "/api/cms/assets/[id]", entrypoint: "@kidecms/core/routes/api/cms/assets/[id].ts" });
|
|
206
212
|
injectRoute({ pattern: "/api/cms/assets", entrypoint: "@kidecms/core/routes/api/cms/assets/index.ts" });
|
|
207
213
|
injectRoute({ pattern: "/api/cms/ai/alt-text", entrypoint: "@kidecms/core/routes/api/cms/ai/alt-text.ts" });
|
|
@@ -215,7 +221,10 @@ export default function cmsIntegration(options) {
|
|
|
215
221
|
// Preview render route uses Astro Container API which depends on Vite internals.
|
|
216
222
|
// Only inject in dev mode — production builds (especially Cloudflare Workers) can't bundle it.
|
|
217
223
|
if (command === "dev") {
|
|
218
|
-
injectRoute({
|
|
224
|
+
injectRoute({
|
|
225
|
+
pattern: "/api/cms/preview/render",
|
|
226
|
+
entrypoint: "@kidecms/core/routes/api/cms/preview/render.ts",
|
|
227
|
+
});
|
|
219
228
|
}
|
|
220
229
|
injectRoute({
|
|
221
230
|
pattern: "/api/cms/references/[collection]/[id]",
|
|
@@ -228,6 +237,9 @@ export default function cmsIntegration(options) {
|
|
|
228
237
|
});
|
|
229
238
|
// Inject auth middleware
|
|
230
239
|
addMiddleware({ entrypoint: "@kidecms/core/middleware/auth.ts", order: "pre" });
|
|
240
|
+
// Inject live-preview client script (no-op unless ?preview is in the URL)
|
|
241
|
+
const previewClient = path.join(corePkgDir, "client", "preview.ts");
|
|
242
|
+
injectScript("page", `import ${JSON.stringify(previewClient)};`);
|
|
231
243
|
// Generate schema, types, validators, and API
|
|
232
244
|
console.log(" [cms] Generating schema, types, validators, and API...");
|
|
233
245
|
try {
|
package/dist/locks.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const acquireLock: (collection: string, documentId: string, userId: string, userEmail: string) => Promise<{
|
|
2
|
+
acquired: true;
|
|
3
|
+
} | {
|
|
4
|
+
acquired: false;
|
|
5
|
+
userEmail: string;
|
|
6
|
+
}>;
|
|
7
|
+
export declare const releaseLock: (collection: string, documentId: string, userId: string) => Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createRichTextFromPlainText, renderRichText, richTextToPlainText } from "./values";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type CmsStorageAdapter = {
|
|
2
|
+
putFile: (storagePath: string, data: ArrayBuffer | Uint8Array) => Promise<void>;
|
|
3
|
+
getFile: (storagePath: string) => Promise<ArrayBuffer | null>;
|
|
4
|
+
deleteFile: (storagePath: string) => Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
export type CmsEmailAdapter = {
|
|
7
|
+
sendInviteEmail: (to: string, inviteUrl: string) => Promise<boolean>;
|
|
8
|
+
isEmailConfigured: () => boolean;
|
|
9
|
+
};
|
|
10
|
+
export type CmsRuntimeConfig = {
|
|
11
|
+
getDb: () => Promise<any>;
|
|
12
|
+
closeDb?: () => void;
|
|
13
|
+
storage: CmsStorageAdapter;
|
|
14
|
+
email?: CmsEmailAdapter;
|
|
15
|
+
env?: (key: string) => string | undefined;
|
|
16
|
+
};
|
|
17
|
+
export declare const configureCmsRuntime: (config: CmsRuntimeConfig) => void;
|
|
18
|
+
export declare const resetCmsRuntime: () => void;
|
|
19
|
+
export declare const getCmsRuntime: () => CmsRuntimeConfig;
|
|
20
|
+
export declare const getDb: () => Promise<any>;
|
|
21
|
+
export declare const closeDb: () => void;
|
|
22
|
+
export declare const getStorage: () => CmsStorageAdapter;
|
|
23
|
+
export declare const getEmail: () => CmsEmailAdapter;
|
|
24
|
+
export declare const readEnv: (key: string) => string | undefined;
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type SchemaModule = {
|
|
2
|
+
cmsTables: Record<string, {
|
|
3
|
+
main: any;
|
|
4
|
+
translations?: any;
|
|
5
|
+
versions?: any;
|
|
6
|
+
}>;
|
|
7
|
+
cmsAssets: any;
|
|
8
|
+
cmsAssetFolders: any;
|
|
9
|
+
cmsSessions: any;
|
|
10
|
+
cmsLocks: any;
|
|
11
|
+
cmsInvites: any;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
};
|
|
14
|
+
export declare const initSchema: (nextSchema: SchemaModule) => void;
|
|
15
|
+
export declare const resetSchema: () => void;
|
|
16
|
+
export declare const getSchema: () => SchemaModule;
|
|
17
|
+
export {};
|
package/dist/seed.d.ts
ADDED
package/dist/values.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FieldConfig, RichTextDocument } from "./define";
|
|
2
|
+
export declare const cloneValue: <T>(value: T) => T;
|
|
3
|
+
export declare const slugify: (value: string) => string;
|
|
4
|
+
export declare const escapeHtml: (value: string) => string;
|
|
5
|
+
export declare const createRichTextFromPlainText: (text: string) => RichTextDocument;
|
|
6
|
+
export declare const renderRichText: (document?: RichTextDocument | null) => string;
|
|
7
|
+
export declare const richTextToPlainText: (document?: RichTextDocument | null) => string;
|
|
8
|
+
export declare const serializeFieldValue: (field: FieldConfig, value: unknown) => string;
|
package/dist/webhooks.js
CHANGED
|
@@ -61,7 +61,9 @@ export async function dispatchWebhooks(config, event, collectionSlug, doc, user)
|
|
|
61
61
|
};
|
|
62
62
|
// Fire all matching webhooks in parallel — don't block the operation
|
|
63
63
|
for (const webhook of matching) {
|
|
64
|
-
const payload = webhook.payload
|
|
64
|
+
const payload = webhook.payload
|
|
65
|
+
? webhook.payload(doc, context)
|
|
66
|
+
: { event, collection: collectionSlug, doc, user, timestamp: context.timestamp };
|
|
65
67
|
const body = JSON.stringify(payload);
|
|
66
68
|
// Fire and forget — failures are logged but don't bubble up
|
|
67
69
|
deliverWebhook(webhook, body).catch((err) => {
|
package/package.json
CHANGED
|
@@ -232,7 +232,10 @@ if (collection && collectionSlug && canAccessCurrent) {
|
|
|
232
232
|
return Astro.redirect(`/admin/${collectionSlug}/${(await collectionApi.create({}, runtimeContext))._id}`);
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
for (const [fieldName, field] of Object.entries(collection.fields) as [
|
|
235
|
+
for (const [fieldName, field] of Object.entries(collection.fields) as [
|
|
236
|
+
string,
|
|
237
|
+
import("@kidecms/core").FieldConfig,
|
|
238
|
+
][]) {
|
|
236
239
|
if (field.type === "relation" && canRead(field.collection)) {
|
|
237
240
|
const relatedDocs = await cmsRuntime[field.collection].find(
|
|
238
241
|
{
|
|
@@ -47,7 +47,12 @@ const assetData = folderAssets.map((a) => ({
|
|
|
47
47
|
}));
|
|
48
48
|
---
|
|
49
49
|
|
|
50
|
-
<AdminLayout
|
|
50
|
+
<AdminLayout
|
|
51
|
+
title="Assets | Kide CMS"
|
|
52
|
+
collections={accessibleCollections}
|
|
53
|
+
activeCollection="assets"
|
|
54
|
+
customNav={config.admin?.nav}
|
|
55
|
+
>
|
|
51
56
|
<AssetsGrid
|
|
52
57
|
client:load
|
|
53
58
|
folders={folderData}
|