@bobbykim/manguito-cms-core 0.1.0
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/dist/index.d.mts +527 -0
- package/dist/index.d.ts +527 -0
- package/dist/index.js +1165 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1119 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +39 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
type SchemaFolders = {
|
|
2
|
+
content_types: string;
|
|
3
|
+
paragraph_types: string;
|
|
4
|
+
taxonomy_types: string;
|
|
5
|
+
enum_types: string;
|
|
6
|
+
};
|
|
7
|
+
type SchemaConfig = {
|
|
8
|
+
base_path?: string;
|
|
9
|
+
folders?: Partial<SchemaFolders>;
|
|
10
|
+
};
|
|
11
|
+
type ResolvedSchemaConfig = {
|
|
12
|
+
base_path: string;
|
|
13
|
+
folders: SchemaFolders;
|
|
14
|
+
};
|
|
15
|
+
type MigrationsConfig = {
|
|
16
|
+
table?: string;
|
|
17
|
+
folder?: string;
|
|
18
|
+
};
|
|
19
|
+
type ResolvedMigrationsConfig = {
|
|
20
|
+
table: string;
|
|
21
|
+
folder: string;
|
|
22
|
+
} | null;
|
|
23
|
+
type MigrationResult = {
|
|
24
|
+
applied: number;
|
|
25
|
+
skipped: number;
|
|
26
|
+
};
|
|
27
|
+
type MigrationStatus = {
|
|
28
|
+
pending: string[];
|
|
29
|
+
applied: string[];
|
|
30
|
+
};
|
|
31
|
+
interface DbAdapter {
|
|
32
|
+
readonly type: 'postgres' | 'mongodb';
|
|
33
|
+
connect(): Promise<void>;
|
|
34
|
+
disconnect(): Promise<void>;
|
|
35
|
+
isConnected(): boolean;
|
|
36
|
+
getTableNames(): Promise<string[]>;
|
|
37
|
+
tableExists(name: string): Promise<boolean>;
|
|
38
|
+
}
|
|
39
|
+
type PresignedOptions = {
|
|
40
|
+
folder: 'image' | 'video' | 'file';
|
|
41
|
+
filename: string;
|
|
42
|
+
mime_type: string;
|
|
43
|
+
expires_in?: number;
|
|
44
|
+
};
|
|
45
|
+
type PresignedResult = {
|
|
46
|
+
upload_url: string;
|
|
47
|
+
key: string;
|
|
48
|
+
expires_at: number;
|
|
49
|
+
method?: 'PUT' | 'POST';
|
|
50
|
+
fields?: Record<string, string>;
|
|
51
|
+
};
|
|
52
|
+
interface StorageAdapter {
|
|
53
|
+
readonly type: 'local' | 's3' | 'cloudinary';
|
|
54
|
+
delete(key: string): Promise<void>;
|
|
55
|
+
getUrl(key: string): string;
|
|
56
|
+
getPresignedUploadUrl(options: PresignedOptions): Promise<PresignedResult>;
|
|
57
|
+
upload?(key: string, data: Uint8Array, mimeType: string): Promise<void>;
|
|
58
|
+
/** Optional metadata lookup used to validate uploaded objects on confirm. */
|
|
59
|
+
stat?(key: string): Promise<{
|
|
60
|
+
size: number;
|
|
61
|
+
content_type?: string;
|
|
62
|
+
} | null>;
|
|
63
|
+
/**
|
|
64
|
+
* Cross-origin hosts the browser connects to during a presigned upload,
|
|
65
|
+
* as CSP connect-src origins (scheme + host, no path). Used to build the
|
|
66
|
+
* Content-Security-Policy. Adapters whose uploads are same-origin (local)
|
|
67
|
+
* omit this.
|
|
68
|
+
*/
|
|
69
|
+
getUploadOrigins?(): string[];
|
|
70
|
+
}
|
|
71
|
+
type CorsConfig = {
|
|
72
|
+
enabled?: boolean;
|
|
73
|
+
origin: string | string[];
|
|
74
|
+
methods?: string[];
|
|
75
|
+
credentials?: boolean;
|
|
76
|
+
};
|
|
77
|
+
interface ServerAdapter {
|
|
78
|
+
readonly type: 'node' | 'lambda' | 'vercel';
|
|
79
|
+
getEntryPoint(): string;
|
|
80
|
+
cors: CorsConfig;
|
|
81
|
+
}
|
|
82
|
+
type ResolvedMediaConfig = {
|
|
83
|
+
max_file_size?: number;
|
|
84
|
+
};
|
|
85
|
+
type ResolvedRateLimitConfig = {
|
|
86
|
+
/**
|
|
87
|
+
* Rate limiting for public list endpoints (paginated collections, not
|
|
88
|
+
* single-item lookups). Set `findAll: '*'` to disable the list-endpoint
|
|
89
|
+
* limiter entirely.
|
|
90
|
+
*/
|
|
91
|
+
findAll?: '*' | {
|
|
92
|
+
windowMs?: number;
|
|
93
|
+
maxPerIp?: number;
|
|
94
|
+
maxGlobal?: number;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
interface APIAdapter {
|
|
98
|
+
readonly prefix: string;
|
|
99
|
+
readonly media?: ResolvedMediaConfig;
|
|
100
|
+
readonly rateLimit?: ResolvedRateLimitConfig;
|
|
101
|
+
}
|
|
102
|
+
interface AdminAdapter {
|
|
103
|
+
readonly prefix: string;
|
|
104
|
+
}
|
|
105
|
+
type ManguitoConfig = {
|
|
106
|
+
name?: string;
|
|
107
|
+
schema?: SchemaConfig;
|
|
108
|
+
db: DbAdapter;
|
|
109
|
+
migrations?: MigrationsConfig;
|
|
110
|
+
storage: StorageAdapter;
|
|
111
|
+
server: ServerAdapter;
|
|
112
|
+
api: APIAdapter;
|
|
113
|
+
admin: AdminAdapter;
|
|
114
|
+
};
|
|
115
|
+
type ResolvedManguitoConfig = {
|
|
116
|
+
name: string;
|
|
117
|
+
schema: ResolvedSchemaConfig;
|
|
118
|
+
db: DbAdapter;
|
|
119
|
+
migrations: ResolvedMigrationsConfig | null;
|
|
120
|
+
storage: StorageAdapter;
|
|
121
|
+
server: ServerAdapter;
|
|
122
|
+
api: APIAdapter;
|
|
123
|
+
admin: AdminAdapter;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
declare function defineConfig(config: ManguitoConfig): ResolvedManguitoConfig;
|
|
127
|
+
|
|
128
|
+
type DbColumnType = 'uuid' | 'varchar' | 'text' | 'integer' | 'decimal' | 'boolean' | 'timestamp';
|
|
129
|
+
type DbColumn = {
|
|
130
|
+
column_name: string;
|
|
131
|
+
column_type: DbColumnType;
|
|
132
|
+
nullable: boolean;
|
|
133
|
+
check_constraint?: string[];
|
|
134
|
+
foreign_key?: {
|
|
135
|
+
table: string;
|
|
136
|
+
column: string;
|
|
137
|
+
on_delete: 'CASCADE' | 'SET NULL' | 'RESTRICT';
|
|
138
|
+
};
|
|
139
|
+
junction?: {
|
|
140
|
+
table_name: string;
|
|
141
|
+
left_column: string;
|
|
142
|
+
right_column: string;
|
|
143
|
+
right_table: string;
|
|
144
|
+
order_column: boolean;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
type FieldValidation = {
|
|
148
|
+
required: boolean;
|
|
149
|
+
min?: number;
|
|
150
|
+
max?: number;
|
|
151
|
+
limit?: number;
|
|
152
|
+
max_size?: number;
|
|
153
|
+
pattern?: string;
|
|
154
|
+
max_items?: number;
|
|
155
|
+
allowed_values?: string[];
|
|
156
|
+
allowed_mime_types?: string[];
|
|
157
|
+
};
|
|
158
|
+
type RelationType = 'one-to-one' | 'one-to-many' | 'many-to-many';
|
|
159
|
+
type UiComponent = {
|
|
160
|
+
component: 'text-input';
|
|
161
|
+
} | {
|
|
162
|
+
component: 'rich-text-editor';
|
|
163
|
+
} | {
|
|
164
|
+
component: 'number-input';
|
|
165
|
+
step: number;
|
|
166
|
+
} | {
|
|
167
|
+
component: 'checkbox';
|
|
168
|
+
} | {
|
|
169
|
+
component: 'date-picker';
|
|
170
|
+
} | {
|
|
171
|
+
component: 'file-upload';
|
|
172
|
+
accepted_mime_types: string[];
|
|
173
|
+
} | {
|
|
174
|
+
component: 'select';
|
|
175
|
+
options: string[];
|
|
176
|
+
enum_ref?: string;
|
|
177
|
+
} | {
|
|
178
|
+
component: 'typeahead-select';
|
|
179
|
+
ref: string;
|
|
180
|
+
rel: RelationType;
|
|
181
|
+
} | {
|
|
182
|
+
component: 'paragraph-embed';
|
|
183
|
+
ref: string;
|
|
184
|
+
rel: RelationType;
|
|
185
|
+
max?: number;
|
|
186
|
+
};
|
|
187
|
+
type FieldType = 'text/plain' | 'text/rich' | 'integer' | 'float' | 'boolean' | 'date' | 'image' | 'video' | 'file' | 'enum' | 'paragraph' | 'reference';
|
|
188
|
+
type ParsedField = {
|
|
189
|
+
name: string;
|
|
190
|
+
label: string;
|
|
191
|
+
field_type: FieldType;
|
|
192
|
+
required: boolean;
|
|
193
|
+
nullable: boolean;
|
|
194
|
+
order: number;
|
|
195
|
+
validation: FieldValidation;
|
|
196
|
+
db_column: DbColumn | null;
|
|
197
|
+
ui_component: UiComponent;
|
|
198
|
+
};
|
|
199
|
+
type SystemField = {
|
|
200
|
+
name: string;
|
|
201
|
+
db_type: 'uuid' | 'timestamp' | 'varchar' | 'boolean' | 'integer';
|
|
202
|
+
primary_key?: boolean;
|
|
203
|
+
default?: string;
|
|
204
|
+
nullable: boolean;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
type Result<T> = {
|
|
208
|
+
ok: true;
|
|
209
|
+
value: T;
|
|
210
|
+
} | {
|
|
211
|
+
ok: false;
|
|
212
|
+
errors: ParseError[];
|
|
213
|
+
};
|
|
214
|
+
type ParseErrorCode = 'INVALID_SCHEMA_TYPE' | 'INVALID_FIELD_TYPE' | 'UNKNOWN_BASE_PATH' | 'UNKNOWN_REF' | 'INVALID_REF_TARGET' | 'DUPLICATE_FIELD_NAME' | 'DUPLICATE_SCHEMA_NAME' | 'INVALID_MACHINE_NAME' | 'CIRCULAR_REFERENCE' | 'MISSING_REQUIRED_FIELD' | 'MAX_SIZE_EXCEEDS_GLOBAL_LIMIT' | 'SCHEMA_DIR_NOT_FOUND' | 'SCHEMA_FOLDER_NOT_FOUND' | 'DUPLICATE_SCHEMA_FOLDER' | 'ROUTES_FILE_NOT_FOUND' | 'FILE_READ_ERROR' | 'FILE_PARSE_ERROR' | 'DUPLICATE_HIERARCHY_LEVEL' | 'UNKNOWN_PERMISSION' | 'INVALID_PERMISSION';
|
|
215
|
+
type ParseError = {
|
|
216
|
+
file: string;
|
|
217
|
+
code: ParseErrorCode;
|
|
218
|
+
message: string;
|
|
219
|
+
path?: string;
|
|
220
|
+
};
|
|
221
|
+
type SchemaType = 'content-type' | 'paragraph-type' | 'taxonomy-type' | 'enum-type';
|
|
222
|
+
type SchemaFile = {
|
|
223
|
+
path: string;
|
|
224
|
+
raw: unknown;
|
|
225
|
+
schema_type: SchemaType;
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* Reads a single JSON or YAML schema file and returns the raw parsed object.
|
|
229
|
+
* Supported extensions: .json, .yaml, .yml
|
|
230
|
+
* Never throws — file system and parse errors are returned as Result failures.
|
|
231
|
+
*/
|
|
232
|
+
declare function loadSchemaFile(filePath: string): Result<unknown>;
|
|
233
|
+
/**
|
|
234
|
+
* Walks each schema folder defined in config and collects all schema files.
|
|
235
|
+
* For each file:
|
|
236
|
+
* - Validates that the filename prefix matches the folder's expected schema type.
|
|
237
|
+
* - Reads and parses the file content via loadSchemaFile.
|
|
238
|
+
*
|
|
239
|
+
* Collects all errors rather than stopping at the first failure.
|
|
240
|
+
* Returns { ok: false, errors } only when structural problems prevent loading;
|
|
241
|
+
* individual file errors are accumulated and returned together.
|
|
242
|
+
*/
|
|
243
|
+
declare function walkSchemaDirectory(config: ResolvedSchemaConfig): Result<SchemaFile[]>;
|
|
244
|
+
|
|
245
|
+
type ParsedSchemaBase = {
|
|
246
|
+
schema_type: SchemaType;
|
|
247
|
+
name: string;
|
|
248
|
+
label: string;
|
|
249
|
+
source_file: string;
|
|
250
|
+
};
|
|
251
|
+
type UiTab = {
|
|
252
|
+
name: string;
|
|
253
|
+
label: string;
|
|
254
|
+
fields: string[];
|
|
255
|
+
};
|
|
256
|
+
type UiMeta = {
|
|
257
|
+
tabs: UiTab[];
|
|
258
|
+
};
|
|
259
|
+
type JunctionTable = {
|
|
260
|
+
table_name: string;
|
|
261
|
+
left_column: string;
|
|
262
|
+
right_column: string;
|
|
263
|
+
right_table: string;
|
|
264
|
+
order_column: boolean;
|
|
265
|
+
};
|
|
266
|
+
type ContentDbMeta = {
|
|
267
|
+
table_name: string;
|
|
268
|
+
junction_tables: JunctionTable[];
|
|
269
|
+
};
|
|
270
|
+
type ParagraphDbMeta = {
|
|
271
|
+
table_name: string;
|
|
272
|
+
};
|
|
273
|
+
type TaxonomyDbMeta = {
|
|
274
|
+
table_name: string;
|
|
275
|
+
};
|
|
276
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
277
|
+
type ContentApiMeta = {
|
|
278
|
+
default_base_path: string;
|
|
279
|
+
http_methods: HttpMethod[];
|
|
280
|
+
collection_path?: string;
|
|
281
|
+
item_path: string;
|
|
282
|
+
};
|
|
283
|
+
type TaxonomyApiMeta = {
|
|
284
|
+
collection_path: string;
|
|
285
|
+
item_path: string;
|
|
286
|
+
};
|
|
287
|
+
type ParsedContentType = ParsedSchemaBase & {
|
|
288
|
+
schema_type: 'content-type';
|
|
289
|
+
only_one: boolean;
|
|
290
|
+
default_base_path: string;
|
|
291
|
+
system_fields: SystemField[];
|
|
292
|
+
fields: ParsedField[];
|
|
293
|
+
ui: UiMeta;
|
|
294
|
+
db: ContentDbMeta;
|
|
295
|
+
api: ContentApiMeta;
|
|
296
|
+
};
|
|
297
|
+
type ParsedParagraphType = ParsedSchemaBase & {
|
|
298
|
+
schema_type: 'paragraph-type';
|
|
299
|
+
system_fields: SystemField[];
|
|
300
|
+
fields: ParsedField[];
|
|
301
|
+
db: ParagraphDbMeta;
|
|
302
|
+
};
|
|
303
|
+
type ParsedTaxonomyType = ParsedSchemaBase & {
|
|
304
|
+
schema_type: 'taxonomy-type';
|
|
305
|
+
system_fields: SystemField[];
|
|
306
|
+
fields: ParsedField[];
|
|
307
|
+
db: TaxonomyDbMeta;
|
|
308
|
+
api: TaxonomyApiMeta;
|
|
309
|
+
};
|
|
310
|
+
type ParsedEnumType = ParsedSchemaBase & {
|
|
311
|
+
schema_type: 'enum-type';
|
|
312
|
+
values: string[];
|
|
313
|
+
};
|
|
314
|
+
type ParsedSchema = ParsedContentType | ParsedParagraphType | ParsedTaxonomyType | ParsedEnumType;
|
|
315
|
+
type ParseResult = {
|
|
316
|
+
ok: true;
|
|
317
|
+
schema: ParsedSchema;
|
|
318
|
+
} | {
|
|
319
|
+
ok: false;
|
|
320
|
+
errors: ParseError[];
|
|
321
|
+
};
|
|
322
|
+
/**
|
|
323
|
+
* Parses a raw schema object (from JSON or YAML) into the corresponding
|
|
324
|
+
* Parsed* type. Returns a ParseResult — never throws for expected failures.
|
|
325
|
+
*
|
|
326
|
+
* sourceFile is optional but should be supplied for accurate error reporting.
|
|
327
|
+
*/
|
|
328
|
+
declare function parseSchema(raw: unknown, schemaType: SchemaType, sourceFile?: string): ParseResult;
|
|
329
|
+
|
|
330
|
+
type PermissionTarget = 'content' | 'media' | 'taxonomy' | 'users' | 'roles';
|
|
331
|
+
type PermissionAction = 'read' | 'create' | 'edit' | 'delete';
|
|
332
|
+
type Permission = `${PermissionTarget}:${PermissionAction}`;
|
|
333
|
+
type JWTPayload = {
|
|
334
|
+
user_id: string;
|
|
335
|
+
role: string;
|
|
336
|
+
token_version: number;
|
|
337
|
+
expires_at: number;
|
|
338
|
+
};
|
|
339
|
+
type User = {
|
|
340
|
+
id: string;
|
|
341
|
+
email: string;
|
|
342
|
+
password_hash: string;
|
|
343
|
+
role_id: string;
|
|
344
|
+
token_version: number;
|
|
345
|
+
must_change_password: boolean;
|
|
346
|
+
created_at: Date;
|
|
347
|
+
updated_at: Date;
|
|
348
|
+
};
|
|
349
|
+
type FilterOperator = {
|
|
350
|
+
gt?: number | string;
|
|
351
|
+
gte?: number | string;
|
|
352
|
+
lt?: number | string;
|
|
353
|
+
lte?: number | string;
|
|
354
|
+
};
|
|
355
|
+
type FilterValue = string | number | boolean | Array<string | number | boolean> | FilterOperator;
|
|
356
|
+
type PaginatedResult<T> = {
|
|
357
|
+
ok: true;
|
|
358
|
+
data: T[];
|
|
359
|
+
meta: {
|
|
360
|
+
total: number;
|
|
361
|
+
page: number;
|
|
362
|
+
per_page: number;
|
|
363
|
+
total_pages: number;
|
|
364
|
+
has_next: boolean;
|
|
365
|
+
has_prev: boolean;
|
|
366
|
+
};
|
|
367
|
+
};
|
|
368
|
+
type FindManyOptions = {
|
|
369
|
+
page?: number;
|
|
370
|
+
per_page?: number;
|
|
371
|
+
include?: string[];
|
|
372
|
+
published_only?: boolean;
|
|
373
|
+
filters?: Record<string, FilterValue>;
|
|
374
|
+
sort_by?: 'title' | 'created_at' | 'updated_at';
|
|
375
|
+
sort_order?: 'asc' | 'desc';
|
|
376
|
+
search?: {
|
|
377
|
+
term: string;
|
|
378
|
+
columns: string[];
|
|
379
|
+
};
|
|
380
|
+
};
|
|
381
|
+
type FindAllOptions = {
|
|
382
|
+
include?: string[];
|
|
383
|
+
published_only?: boolean;
|
|
384
|
+
};
|
|
385
|
+
type CreateInput<T> = Omit<T, 'id' | 'created_at' | 'updated_at'>;
|
|
386
|
+
type UpdateInput<T> = Partial<Omit<T, 'id' | 'created_at' | 'updated_at'>>;
|
|
387
|
+
interface ContentRepository<T> {
|
|
388
|
+
findMany(options: FindManyOptions): Promise<PaginatedResult<T>>;
|
|
389
|
+
findOne(id: string, include?: string[]): Promise<T | null>;
|
|
390
|
+
findBySlug(slug: string, include?: string[]): Promise<T | null>;
|
|
391
|
+
create(data: CreateInput<T>): Promise<T>;
|
|
392
|
+
update(id: string, data: UpdateInput<T>): Promise<T | null>;
|
|
393
|
+
delete(id: string): Promise<void>;
|
|
394
|
+
findAll(options: FindAllOptions): Promise<T[]>;
|
|
395
|
+
}
|
|
396
|
+
type MediaItem = {
|
|
397
|
+
id: string;
|
|
398
|
+
type: 'image' | 'video' | 'file';
|
|
399
|
+
url: string;
|
|
400
|
+
mime_type: string;
|
|
401
|
+
alt?: string;
|
|
402
|
+
file_size: number;
|
|
403
|
+
width?: number;
|
|
404
|
+
height?: number;
|
|
405
|
+
duration?: number;
|
|
406
|
+
reference_count: number;
|
|
407
|
+
created_at: Date;
|
|
408
|
+
updated_at: Date;
|
|
409
|
+
};
|
|
410
|
+
type CreateMediaInput = {
|
|
411
|
+
type: 'image' | 'video' | 'file';
|
|
412
|
+
url: string;
|
|
413
|
+
mime_type: string;
|
|
414
|
+
alt?: string;
|
|
415
|
+
file_size: number;
|
|
416
|
+
width?: number;
|
|
417
|
+
height?: number;
|
|
418
|
+
duration?: number;
|
|
419
|
+
};
|
|
420
|
+
type MediaFindManyOptions = {
|
|
421
|
+
page?: number;
|
|
422
|
+
per_page?: number;
|
|
423
|
+
type?: 'image' | 'video' | 'file';
|
|
424
|
+
orphaned?: boolean;
|
|
425
|
+
};
|
|
426
|
+
interface MediaRepository {
|
|
427
|
+
findMany(options: MediaFindManyOptions): Promise<PaginatedResult<MediaItem>>;
|
|
428
|
+
findOne(id: string): Promise<MediaItem | null>;
|
|
429
|
+
create(data: CreateMediaInput): Promise<MediaItem>;
|
|
430
|
+
update(id: string, data: Partial<MediaItem>): Promise<MediaItem | null>;
|
|
431
|
+
delete(id: string): Promise<void>;
|
|
432
|
+
incrementReferenceCount(ids: string[]): Promise<void>;
|
|
433
|
+
decrementReferenceCount(ids: string[]): Promise<void>;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
type ParsedBasePath = {
|
|
437
|
+
name: string;
|
|
438
|
+
path: string;
|
|
439
|
+
};
|
|
440
|
+
type ParsedRoutes = {
|
|
441
|
+
base_paths: ParsedBasePath[];
|
|
442
|
+
};
|
|
443
|
+
type ParsedRole = {
|
|
444
|
+
name: string;
|
|
445
|
+
label: string;
|
|
446
|
+
is_system: boolean;
|
|
447
|
+
hierarchy_level: number;
|
|
448
|
+
permissions: Permission[];
|
|
449
|
+
};
|
|
450
|
+
type ParsedRoles = {
|
|
451
|
+
roles: ParsedRole[];
|
|
452
|
+
valid_permissions: string[];
|
|
453
|
+
};
|
|
454
|
+
type SchemaRegistry = {
|
|
455
|
+
routes: ParsedRoutes;
|
|
456
|
+
roles: ParsedRoles;
|
|
457
|
+
/** All schemas keyed by machine name. When two schemas share a name, last-write-wins. */
|
|
458
|
+
schemas: Record<string, ParsedSchema>;
|
|
459
|
+
content_types: Record<string, ParsedContentType>;
|
|
460
|
+
paragraph_types: Record<string, ParsedParagraphType>;
|
|
461
|
+
taxonomy_types: Record<string, ParsedTaxonomyType>;
|
|
462
|
+
enum_types: Record<string, ParsedEnumType>;
|
|
463
|
+
/**
|
|
464
|
+
* All schemas in the original input order, preserving duplicates.
|
|
465
|
+
* Used by validateCrossReferences to detect DUPLICATE_SCHEMA_NAME errors —
|
|
466
|
+
* the keyed maps above deduplicate by name and would hide them.
|
|
467
|
+
*/
|
|
468
|
+
all_schemas: readonly ParsedSchema[];
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* Assembles the final SchemaRegistry from all individually parsed schemas,
|
|
472
|
+
* routes, and roles.
|
|
473
|
+
*
|
|
474
|
+
* When two schemas share the same machine name, last-write-wins in the keyed
|
|
475
|
+
* maps. The all_schemas array preserves all entries (including duplicates) so
|
|
476
|
+
* that validateCrossReferences can detect DUPLICATE_SCHEMA_NAME errors.
|
|
477
|
+
*
|
|
478
|
+
* Also resolves enum refs: any enum field that uses `ref` (rather than inline
|
|
479
|
+
* `values`) has its allowed_values, check_constraint, and select options
|
|
480
|
+
* populated from the matching enum-type schema. Fields whose enum ref does not
|
|
481
|
+
* exist in the registry are left empty — validateCrossReferences will report
|
|
482
|
+
* UNKNOWN_REF for them.
|
|
483
|
+
*/
|
|
484
|
+
declare function buildSchemaRegistry(parsedSchemas: ParsedSchema[], parsedRoutes: ParsedRoutes, parsedRoles: ParsedRoles): SchemaRegistry;
|
|
485
|
+
/**
|
|
486
|
+
* Validates cross-schema references after all schemas have been individually
|
|
487
|
+
* parsed and assembled into a registry. Returns all cross-reference errors.
|
|
488
|
+
*
|
|
489
|
+
* Error codes covered:
|
|
490
|
+
* - DUPLICATE_SCHEMA_NAME — two schema files share the same machine name
|
|
491
|
+
* - UNKNOWN_REF — ref or target points to a non-existent schema
|
|
492
|
+
* - INVALID_REF_TARGET — ref points to a schema of the wrong type
|
|
493
|
+
* - CIRCULAR_REFERENCE — paragraph A refs paragraph B which refs paragraph A
|
|
494
|
+
* - MAX_SIZE_EXCEEDS_GLOBAL_LIMIT — field max_size exceeds the global limit
|
|
495
|
+
*
|
|
496
|
+
* @param registry The assembled SchemaRegistry (from buildSchemaRegistry).
|
|
497
|
+
* @param globalMaxFileSize Global max file size in bytes from api.media.max_file_size.
|
|
498
|
+
* When provided, MAX_SIZE_EXCEEDS_GLOBAL_LIMIT is checked for all media fields.
|
|
499
|
+
*/
|
|
500
|
+
declare function validateCrossReferences(registry: SchemaRegistry, globalMaxFileSize?: number): ParseError[];
|
|
501
|
+
/**
|
|
502
|
+
* Validates a raw routes.json object and produces a ParsedRoutes value.
|
|
503
|
+
* Returns Result<ParsedRoutes> — never throws for expected failures.
|
|
504
|
+
* sourceFile is optional; supply it for accurate error file paths.
|
|
505
|
+
*/
|
|
506
|
+
declare function parseRoutes(raw: unknown, sourceFile?: string): Result<ParsedRoutes>;
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Validates a raw roles.json object and produces a ParsedRoles value.
|
|
510
|
+
*
|
|
511
|
+
* Validation rules (all errors are accumulated — none stop early):
|
|
512
|
+
* MISSING_REQUIRED_FIELD — name, label, hierarchy_level, or permissions absent
|
|
513
|
+
* INVALID_PERMISSION — roles:create, roles:edit, or roles:delete present
|
|
514
|
+
* UNKNOWN_PERMISSION — any other unrecognised permission string
|
|
515
|
+
* DUPLICATE_HIERARCHY_LEVEL — two roles share the same hierarchy_level value
|
|
516
|
+
*
|
|
517
|
+
* Returns Result<ParsedRoles> — never throws for expected failures.
|
|
518
|
+
* sourceFile is optional; supply it for accurate error file paths.
|
|
519
|
+
*/
|
|
520
|
+
declare function parseRoles(raw: unknown, sourceFile?: string): Result<ParsedRoles>;
|
|
521
|
+
|
|
522
|
+
type ErrorCode = ParseErrorCode | 'NOT_FOUND' | 'SLUG_NOT_FOUND' | 'METHOD_NOT_ALLOWED' | 'INTERNAL_ERROR' | 'VALIDATION_ERROR' | 'INVALID_SLUG_FORMAT' | 'SLUG_CONFLICT' | 'PUBLISH_VALIDATION_ERROR' | 'SINGLETON_ALREADY_EXISTS' | 'UNAUTHORIZED' | 'TOKEN_EXPIRED' | 'TOKEN_INVALID' | 'INSUFFICIENT_PERMISSION' | 'INSUFFICIENT_PRIVILEGE' | 'INVALID_FILTER_FIELD' | 'INVALID_FILTER_OPERATOR' | 'INVALID_SORT_FIELD' | 'INVALID_PAGINATION' | 'INVALID_INCLUDE_FIELD' | 'UNSUPPORTED_MIME_TYPE' | 'STORAGE_ERROR' | 'MEDIA_IN_USE' | 'PRESIGNED_URL_EXPIRED' | 'FILE_TOO_LARGE' | 'RATE_LIMITED' | 'INVALID_CREDENTIALS' | 'PASSWORD_CHANGE_REQUIRED' | 'INVALID_ROLE';
|
|
523
|
+
|
|
524
|
+
declare function hashPassword(password: string): Promise<string>;
|
|
525
|
+
declare function verifyPassword(password: string, stored: string): Promise<boolean>;
|
|
526
|
+
|
|
527
|
+
export { type APIAdapter, type AdminAdapter, type ContentDbMeta, type ContentRepository, type CorsConfig, type CreateInput, type CreateMediaInput, type DbAdapter, type DbColumn, type DbColumnType, type ErrorCode, type FieldType, type FieldValidation, type FilterOperator, type FilterValue, type FindAllOptions, type FindManyOptions, type JWTPayload, type JunctionTable, type ManguitoConfig, type MediaFindManyOptions, type MediaItem, type MediaRepository, type MigrationResult, type MigrationStatus, type MigrationsConfig, type PaginatedResult, type ParagraphDbMeta, type ParseError, type ParseErrorCode, type ParseResult, type ParsedBasePath, type ParsedContentType, type ParsedEnumType, type ParsedField, type ParsedParagraphType, type ParsedRole, type ParsedRoles, type ParsedRoutes, type ParsedSchema, type ParsedSchemaBase, type ParsedTaxonomyType, type Permission, type PermissionAction, type PermissionTarget, type PresignedOptions, type PresignedResult, type RelationType, type ResolvedManguitoConfig, type ResolvedMediaConfig, type ResolvedMigrationsConfig, type ResolvedRateLimitConfig, type ResolvedSchemaConfig, type Result, type SchemaConfig, type SchemaFile, type SchemaFolders, type SchemaRegistry, type SchemaType, type ServerAdapter, type StorageAdapter, type SystemField, type TaxonomyDbMeta, type UiComponent, type UiMeta, type UiTab, type UpdateInput, type User, buildSchemaRegistry, defineConfig, hashPassword, loadSchemaFile, parseRoles, parseRoutes, parseSchema, validateCrossReferences, verifyPassword, walkSchemaDirectory };
|