@momentumcms/server-core 0.0.1
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/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/index.cjs +5254 -0
- package/package.json +40 -0
- package/src/index.d.ts +21 -0
- package/src/lib/api-keys.d.ts +105 -0
- package/src/lib/collection-access.d.ts +54 -0
- package/src/lib/field-access.d.ts +28 -0
- package/src/lib/field-hooks.d.ts +21 -0
- package/src/lib/graphql-handler.d.ts +25 -0
- package/src/lib/graphql-scalars.d.ts +6 -0
- package/src/lib/graphql-schema.d.ts +16 -0
- package/src/lib/import-export.d.ts +75 -0
- package/src/lib/momentum-api.d.ts +51 -0
- package/src/lib/momentum-api.types.d.ts +368 -0
- package/src/lib/openapi-generator.d.ts +45 -0
- package/src/lib/preview-renderer.d.ts +27 -0
- package/src/lib/publish-scheduler.d.ts +35 -0
- package/src/lib/rate-limiter.d.ts +20 -0
- package/src/lib/relationship-populator.d.ts +27 -0
- package/src/lib/seeding/index.d.ts +7 -0
- package/src/lib/seeding/seed-executor.d.ts +92 -0
- package/src/lib/seeding/seed-tracker.d.ts +72 -0
- package/src/lib/server-core.d.ts +71 -0
- package/src/lib/shared-server-utils.d.ts +20 -0
- package/src/lib/swagger-ui-html.d.ts +5 -0
- package/src/lib/upload-handler.d.ts +72 -0
- package/src/lib/version-operations.d.ts +33 -0
- package/src/lib/webhooks.d.ts +28 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Momentum API Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the Momentum API - a unified interface for
|
|
5
|
+
* direct database access (server-side) and HTTP calls (browser-side).
|
|
6
|
+
*/
|
|
7
|
+
import type { MomentumConfig, UserContext, DocumentStatus, DocumentVersionParsed, VersionQueryResult, VersionQueryOptions, RestoreVersionOptions, PublishOptions, SchedulePublishResult } from '@momentumcms/core';
|
|
8
|
+
/**
|
|
9
|
+
* Context passed to API operations.
|
|
10
|
+
* Used for access control and hook execution.
|
|
11
|
+
*/
|
|
12
|
+
export interface MomentumAPIContext {
|
|
13
|
+
/** Current authenticated user */
|
|
14
|
+
user?: UserContext;
|
|
15
|
+
/** Depth for relationship population */
|
|
16
|
+
depth?: number;
|
|
17
|
+
/** Show hidden fields (admin only) */
|
|
18
|
+
showHiddenFields?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Options for find operations.
|
|
22
|
+
*/
|
|
23
|
+
export interface FindOptions {
|
|
24
|
+
/** Filter conditions */
|
|
25
|
+
where?: WhereClause;
|
|
26
|
+
/** Sort field (prefix with - for descending) */
|
|
27
|
+
sort?: string;
|
|
28
|
+
/** Maximum documents to return */
|
|
29
|
+
limit?: number;
|
|
30
|
+
/** Page number (1-indexed) */
|
|
31
|
+
page?: number;
|
|
32
|
+
/** Depth for relationship population */
|
|
33
|
+
depth?: number;
|
|
34
|
+
/** Include soft-deleted documents in results (only for collections with softDelete enabled). @default false */
|
|
35
|
+
withDeleted?: boolean;
|
|
36
|
+
/** Only return soft-deleted documents (only for collections with softDelete enabled). @default false */
|
|
37
|
+
onlyDeleted?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Where clause for filtering documents.
|
|
41
|
+
* Supports field-level operators like equals, contains, etc.
|
|
42
|
+
*/
|
|
43
|
+
export type WhereClause = Record<string, unknown>;
|
|
44
|
+
/**
|
|
45
|
+
* Result of a find operation with pagination info.
|
|
46
|
+
*/
|
|
47
|
+
export interface FindResult<T> {
|
|
48
|
+
/** Array of documents */
|
|
49
|
+
docs: T[];
|
|
50
|
+
/** Total number of matching documents */
|
|
51
|
+
totalDocs: number;
|
|
52
|
+
/** Total number of pages */
|
|
53
|
+
totalPages: number;
|
|
54
|
+
/** Current page number */
|
|
55
|
+
page: number;
|
|
56
|
+
/** Documents per page */
|
|
57
|
+
limit: number;
|
|
58
|
+
/** Whether there's a next page */
|
|
59
|
+
hasNextPage: boolean;
|
|
60
|
+
/** Whether there's a previous page */
|
|
61
|
+
hasPrevPage: boolean;
|
|
62
|
+
/** Next page number (if exists) */
|
|
63
|
+
nextPage?: number;
|
|
64
|
+
/** Previous page number (if exists) */
|
|
65
|
+
prevPage?: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Result of a delete operation.
|
|
69
|
+
*/
|
|
70
|
+
export interface DeleteResult {
|
|
71
|
+
/** ID of the deleted document */
|
|
72
|
+
id: string;
|
|
73
|
+
/** Whether deletion was successful */
|
|
74
|
+
deleted: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Operations available on a collection.
|
|
78
|
+
* Generic type T represents the document type.
|
|
79
|
+
*/
|
|
80
|
+
export interface CollectionOperations<T = Record<string, unknown>> {
|
|
81
|
+
/**
|
|
82
|
+
* Find multiple documents matching the query.
|
|
83
|
+
*/
|
|
84
|
+
find(options?: FindOptions): Promise<FindResult<T>>;
|
|
85
|
+
/**
|
|
86
|
+
* Find a single document by ID.
|
|
87
|
+
*/
|
|
88
|
+
findById(id: string, options?: {
|
|
89
|
+
depth?: number;
|
|
90
|
+
withDeleted?: boolean;
|
|
91
|
+
}): Promise<T | null>;
|
|
92
|
+
/**
|
|
93
|
+
* Create a new document.
|
|
94
|
+
*/
|
|
95
|
+
create(data: Partial<T>): Promise<T>;
|
|
96
|
+
/**
|
|
97
|
+
* Update an existing document.
|
|
98
|
+
*/
|
|
99
|
+
update(id: string, data: Partial<T>): Promise<T>;
|
|
100
|
+
/**
|
|
101
|
+
* Delete a document.
|
|
102
|
+
* For collections with softDelete enabled, this sets deletedAt instead of removing the row.
|
|
103
|
+
*/
|
|
104
|
+
delete(id: string): Promise<DeleteResult>;
|
|
105
|
+
/**
|
|
106
|
+
* Permanently delete a document, bypassing soft delete.
|
|
107
|
+
* For collections without softDelete, this is identical to delete().
|
|
108
|
+
*/
|
|
109
|
+
forceDelete(id: string): Promise<DeleteResult>;
|
|
110
|
+
/**
|
|
111
|
+
* Restore a soft-deleted document.
|
|
112
|
+
* Only available for collections with softDelete enabled.
|
|
113
|
+
* Throws if the document is not soft-deleted or softDelete is not enabled.
|
|
114
|
+
*/
|
|
115
|
+
restore(id: string): Promise<T>;
|
|
116
|
+
/**
|
|
117
|
+
* Full-text search across collection fields.
|
|
118
|
+
* Searches text/textarea/email fields using database full-text search.
|
|
119
|
+
*
|
|
120
|
+
* @param query - The search query string
|
|
121
|
+
* @param options - Search options (fields to search, pagination)
|
|
122
|
+
* @returns Search results sorted by relevance
|
|
123
|
+
*/
|
|
124
|
+
search(query: string, options?: {
|
|
125
|
+
fields?: string[];
|
|
126
|
+
limit?: number;
|
|
127
|
+
page?: number;
|
|
128
|
+
}): Promise<FindResult<T>>;
|
|
129
|
+
/**
|
|
130
|
+
* Count documents matching the query.
|
|
131
|
+
*/
|
|
132
|
+
count(where?: WhereClause, options?: {
|
|
133
|
+
withDeleted?: boolean;
|
|
134
|
+
}): Promise<number>;
|
|
135
|
+
/**
|
|
136
|
+
* Create multiple documents in a single transaction.
|
|
137
|
+
* All documents are created or none (atomic).
|
|
138
|
+
*
|
|
139
|
+
* @param items - Array of document data to create
|
|
140
|
+
* @returns Array of created documents
|
|
141
|
+
*/
|
|
142
|
+
batchCreate(items: Partial<T>[]): Promise<T[]>;
|
|
143
|
+
/**
|
|
144
|
+
* Update multiple documents in a single transaction.
|
|
145
|
+
* All updates succeed or none (atomic).
|
|
146
|
+
*
|
|
147
|
+
* @param items - Array of { id, data } pairs to update
|
|
148
|
+
* @returns Array of updated documents
|
|
149
|
+
*/
|
|
150
|
+
batchUpdate(items: {
|
|
151
|
+
id: string;
|
|
152
|
+
data: Partial<T>;
|
|
153
|
+
}[]): Promise<T[]>;
|
|
154
|
+
/**
|
|
155
|
+
* Delete multiple documents in a single transaction.
|
|
156
|
+
* All deletions succeed or none (atomic).
|
|
157
|
+
*
|
|
158
|
+
* @param ids - Array of document IDs to delete
|
|
159
|
+
* @returns Array of deletion results
|
|
160
|
+
*/
|
|
161
|
+
batchDelete(ids: string[]): Promise<DeleteResult[]>;
|
|
162
|
+
/**
|
|
163
|
+
* Get version operations for this collection.
|
|
164
|
+
* Returns null if versioning is not enabled for this collection.
|
|
165
|
+
*/
|
|
166
|
+
versions(): VersionOperations<T> | null;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Options for finding versions.
|
|
170
|
+
*/
|
|
171
|
+
export interface VersionFindOptions extends VersionQueryOptions {
|
|
172
|
+
/** Depth for relationship population in version data */
|
|
173
|
+
depth?: number;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Operations available for managing document versions.
|
|
177
|
+
* Only available for collections with versioning enabled.
|
|
178
|
+
*/
|
|
179
|
+
export interface VersionOperations<T = Record<string, unknown>> {
|
|
180
|
+
/**
|
|
181
|
+
* Find all versions for a document.
|
|
182
|
+
* Returns versions in descending order (newest first) by default.
|
|
183
|
+
*
|
|
184
|
+
* @param parentId - The document ID to get versions for
|
|
185
|
+
* @param options - Query options for pagination and filtering
|
|
186
|
+
*/
|
|
187
|
+
findVersions(parentId: string, options?: VersionFindOptions): Promise<VersionQueryResult<T>>;
|
|
188
|
+
/**
|
|
189
|
+
* Find a specific version by ID.
|
|
190
|
+
*
|
|
191
|
+
* @param versionId - The version ID to retrieve
|
|
192
|
+
*/
|
|
193
|
+
findVersionById(versionId: string): Promise<DocumentVersionParsed<T> | null>;
|
|
194
|
+
/**
|
|
195
|
+
* Restore a document to a previous version.
|
|
196
|
+
* Creates a new version with the restored data.
|
|
197
|
+
*
|
|
198
|
+
* @param options - Restore options including version ID
|
|
199
|
+
* @returns The updated document
|
|
200
|
+
*/
|
|
201
|
+
restore(options: RestoreVersionOptions): Promise<T>;
|
|
202
|
+
/**
|
|
203
|
+
* Publish a document (change status from draft to published).
|
|
204
|
+
* Creates a new published version.
|
|
205
|
+
*
|
|
206
|
+
* @param docId - The document ID to publish
|
|
207
|
+
* @param options - Publish options (e.g., scheduled publish)
|
|
208
|
+
* @returns The published document
|
|
209
|
+
*/
|
|
210
|
+
publish(docId: string, options?: PublishOptions): Promise<T>;
|
|
211
|
+
/**
|
|
212
|
+
* Unpublish a document (change status from published to draft).
|
|
213
|
+
*
|
|
214
|
+
* @param docId - The document ID to unpublish
|
|
215
|
+
* @returns The unpublished document
|
|
216
|
+
*/
|
|
217
|
+
unpublish(docId: string): Promise<T>;
|
|
218
|
+
/**
|
|
219
|
+
* Save a draft version without changing the main document.
|
|
220
|
+
* Used for autosave functionality.
|
|
221
|
+
*
|
|
222
|
+
* @param docId - The document ID to save draft for
|
|
223
|
+
* @param data - The draft data
|
|
224
|
+
* @returns The created draft version
|
|
225
|
+
*/
|
|
226
|
+
saveDraft(docId: string, data: Partial<T>): Promise<DocumentVersionParsed<T>>;
|
|
227
|
+
/**
|
|
228
|
+
* Get the current status of a document.
|
|
229
|
+
*
|
|
230
|
+
* @param docId - The document ID
|
|
231
|
+
* @returns The document status ('draft' or 'published')
|
|
232
|
+
*/
|
|
233
|
+
getStatus(docId: string): Promise<DocumentStatus>;
|
|
234
|
+
/**
|
|
235
|
+
* Compare two versions of a document.
|
|
236
|
+
* Returns the differences between the versions.
|
|
237
|
+
*
|
|
238
|
+
* @param versionId1 - First version ID
|
|
239
|
+
* @param versionId2 - Second version ID
|
|
240
|
+
* @returns Object with field-level differences
|
|
241
|
+
*/
|
|
242
|
+
compare(versionId1: string, versionId2: string): Promise<{
|
|
243
|
+
field: string;
|
|
244
|
+
oldValue: unknown;
|
|
245
|
+
newValue: unknown;
|
|
246
|
+
}[]>;
|
|
247
|
+
/**
|
|
248
|
+
* Schedule a document for future publishing.
|
|
249
|
+
*
|
|
250
|
+
* @param docId - The document ID
|
|
251
|
+
* @param publishAt - ISO date string for when to publish
|
|
252
|
+
* @returns The schedule result with document ID and scheduled date
|
|
253
|
+
*/
|
|
254
|
+
schedulePublish(docId: string, publishAt: string): Promise<SchedulePublishResult>;
|
|
255
|
+
/**
|
|
256
|
+
* Cancel a scheduled publish for a document.
|
|
257
|
+
*
|
|
258
|
+
* @param docId - The document ID
|
|
259
|
+
*/
|
|
260
|
+
cancelScheduledPublish(docId: string): Promise<void>;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Operations available on a global (singleton document).
|
|
264
|
+
* Globals have exactly one document — no create/delete, no pagination.
|
|
265
|
+
*/
|
|
266
|
+
export interface GlobalOperations<T = Record<string, unknown>> {
|
|
267
|
+
/**
|
|
268
|
+
* Read the global document.
|
|
269
|
+
* Auto-creates with default field values if it doesn't exist yet.
|
|
270
|
+
*/
|
|
271
|
+
findOne(options?: {
|
|
272
|
+
depth?: number;
|
|
273
|
+
}): Promise<T>;
|
|
274
|
+
/**
|
|
275
|
+
* Update the global document.
|
|
276
|
+
*/
|
|
277
|
+
update(data: Partial<T>): Promise<T>;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* The main Momentum API interface.
|
|
281
|
+
*
|
|
282
|
+
* Provides access to collection operations with optional context.
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* ```typescript
|
|
286
|
+
* const api = getMomentumAPI();
|
|
287
|
+
*
|
|
288
|
+
* // Untyped usage
|
|
289
|
+
* const posts = await api.collection('posts').find({ limit: 10 });
|
|
290
|
+
*
|
|
291
|
+
* // Typed usage
|
|
292
|
+
* const typedPosts = await api.collection<Post>('posts').find();
|
|
293
|
+
*
|
|
294
|
+
* // With user context
|
|
295
|
+
* const adminApi = api.setContext({ user: currentUser });
|
|
296
|
+
* const result = await adminApi.collection('posts').create({ title: 'New Post' });
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
export interface MomentumAPI {
|
|
300
|
+
/**
|
|
301
|
+
* Get operations for a specific collection.
|
|
302
|
+
*
|
|
303
|
+
* @param slug - The collection slug
|
|
304
|
+
* @returns Collection operations interface
|
|
305
|
+
*/
|
|
306
|
+
collection<T = Record<string, unknown>>(slug: string): CollectionOperations<T>;
|
|
307
|
+
/**
|
|
308
|
+
* Get operations for a global (singleton document).
|
|
309
|
+
*
|
|
310
|
+
* @param slug - The global slug
|
|
311
|
+
* @returns Global operations interface
|
|
312
|
+
*/
|
|
313
|
+
global<T = Record<string, unknown>>(slug: string): GlobalOperations<T>;
|
|
314
|
+
/**
|
|
315
|
+
* Get the current Momentum configuration.
|
|
316
|
+
*/
|
|
317
|
+
getConfig(): MomentumConfig;
|
|
318
|
+
/**
|
|
319
|
+
* Create a new API instance with the specified context.
|
|
320
|
+
* The original instance is not modified (immutable pattern).
|
|
321
|
+
*
|
|
322
|
+
* @param ctx - Context to merge with existing context
|
|
323
|
+
* @returns New API instance with merged context
|
|
324
|
+
*/
|
|
325
|
+
setContext(ctx: MomentumAPIContext): MomentumAPI;
|
|
326
|
+
/**
|
|
327
|
+
* Get the current context.
|
|
328
|
+
*/
|
|
329
|
+
getContext(): MomentumAPIContext;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Error thrown when a collection is not found.
|
|
333
|
+
*/
|
|
334
|
+
export declare class CollectionNotFoundError extends Error {
|
|
335
|
+
constructor(slug: string);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Error thrown when a document is not found.
|
|
339
|
+
*/
|
|
340
|
+
export declare class DocumentNotFoundError extends Error {
|
|
341
|
+
constructor(collection: string, id: string);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Error thrown when access is denied.
|
|
345
|
+
*/
|
|
346
|
+
export declare class AccessDeniedError extends Error {
|
|
347
|
+
constructor(operation: string, collection: string);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Error thrown when a global is not found in the configuration.
|
|
351
|
+
*/
|
|
352
|
+
export declare class GlobalNotFoundError extends Error {
|
|
353
|
+
constructor(slug: string);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Validation error for a specific field.
|
|
357
|
+
*/
|
|
358
|
+
export interface FieldValidationError {
|
|
359
|
+
field: string;
|
|
360
|
+
message: string;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Error thrown when validation fails.
|
|
364
|
+
*/
|
|
365
|
+
export declare class ValidationError extends Error {
|
|
366
|
+
readonly errors: FieldValidationError[];
|
|
367
|
+
constructor(errors: FieldValidationError[]);
|
|
368
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI Spec Generator for Momentum CMS
|
|
3
|
+
*
|
|
4
|
+
* Auto-generates an OpenAPI 3.0 specification from collection configs.
|
|
5
|
+
* Covers standard CRUD routes, versioning, batch operations, search,
|
|
6
|
+
* media upload, and GraphQL endpoints.
|
|
7
|
+
*/
|
|
8
|
+
import type { MomentumConfig } from '@momentumcms/core';
|
|
9
|
+
/** OpenAPI 3.0 document (simplified typing for generation). */
|
|
10
|
+
export interface OpenAPIDocument {
|
|
11
|
+
openapi: string;
|
|
12
|
+
info: {
|
|
13
|
+
title: string;
|
|
14
|
+
version: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
};
|
|
17
|
+
servers?: Array<{
|
|
18
|
+
url: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
}>;
|
|
21
|
+
paths: Record<string, Record<string, unknown>>;
|
|
22
|
+
components: {
|
|
23
|
+
schemas: Record<string, unknown>;
|
|
24
|
+
securitySchemes?: Record<string, unknown>;
|
|
25
|
+
};
|
|
26
|
+
security?: Array<Record<string, string[]>>;
|
|
27
|
+
}
|
|
28
|
+
/** Options for generating the spec. */
|
|
29
|
+
export interface OpenAPIGeneratorOptions {
|
|
30
|
+
/** API title (default: 'Momentum CMS API') */
|
|
31
|
+
title?: string;
|
|
32
|
+
/** API version string (default: '1.0.0') */
|
|
33
|
+
version?: string;
|
|
34
|
+
/** Description for the API */
|
|
35
|
+
description?: string;
|
|
36
|
+
/** Server URLs */
|
|
37
|
+
servers?: Array<{
|
|
38
|
+
url: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Generate an OpenAPI 3.0 specification from a MomentumConfig.
|
|
44
|
+
*/
|
|
45
|
+
export declare function generateOpenAPISpec(config: MomentumConfig, options?: OpenAPIGeneratorOptions): OpenAPIDocument;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preview Renderer for Momentum CMS
|
|
3
|
+
*
|
|
4
|
+
* Generates a styled HTML page from document data and collection config.
|
|
5
|
+
* Used by the built-in preview endpoint to render live previews in the admin iframe.
|
|
6
|
+
*/
|
|
7
|
+
import type { CollectionConfig } from '@momentumcms/core';
|
|
8
|
+
/** Options for rendering a preview HTML page. */
|
|
9
|
+
export interface PreviewRenderOptions {
|
|
10
|
+
/** Document data to render */
|
|
11
|
+
doc: Record<string, unknown>;
|
|
12
|
+
/** Collection configuration */
|
|
13
|
+
collection: CollectionConfig;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Render a styled HTML preview page from document data.
|
|
17
|
+
*
|
|
18
|
+
* The page includes:
|
|
19
|
+
* - Styled rendering of each visible field
|
|
20
|
+
* - Inline CSS for responsive layout
|
|
21
|
+
* - postMessage listener for live updates from the admin form
|
|
22
|
+
*
|
|
23
|
+
* Security: Rich text fields are rendered via textContent by default in the
|
|
24
|
+
* postMessage handler to prevent XSS. The initial server render of rich text
|
|
25
|
+
* is trusted server-side content from the database.
|
|
26
|
+
*/
|
|
27
|
+
export declare function renderPreviewHTML(options: PreviewRenderOptions): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Publish Scheduler
|
|
3
|
+
*
|
|
4
|
+
* Background service that polls for documents scheduled for publishing
|
|
5
|
+
* and publishes them when their scheduled time arrives.
|
|
6
|
+
*/
|
|
7
|
+
import type { DatabaseAdapter, CollectionConfig } from '@momentumcms/core';
|
|
8
|
+
/**
|
|
9
|
+
* Options for the publish scheduler.
|
|
10
|
+
*/
|
|
11
|
+
export interface PublishSchedulerOptions {
|
|
12
|
+
/** Polling interval in milliseconds (default: 10000 = 10s) */
|
|
13
|
+
intervalMs?: number;
|
|
14
|
+
/** Logger function for status messages */
|
|
15
|
+
logger?: (message: string) => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Publish scheduler instance handle.
|
|
19
|
+
*/
|
|
20
|
+
export interface PublishSchedulerHandle {
|
|
21
|
+
/** Stop the scheduler */
|
|
22
|
+
stop(): void;
|
|
23
|
+
/** Run one poll cycle manually (for testing) */
|
|
24
|
+
poll(): Promise<number>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Start a background scheduler that polls for documents with
|
|
28
|
+
* scheduledPublishAt <= now and publishes them.
|
|
29
|
+
*
|
|
30
|
+
* @param adapter - Database adapter
|
|
31
|
+
* @param collections - All collection configs (only versioned ones are checked)
|
|
32
|
+
* @param options - Scheduler options
|
|
33
|
+
* @returns Handle to stop the scheduler
|
|
34
|
+
*/
|
|
35
|
+
export declare function startPublishScheduler(adapter: DatabaseAdapter, collections: CollectionConfig[], options?: PublishSchedulerOptions): PublishSchedulerHandle;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple in-memory rate limiter with automatic cleanup of expired entries.
|
|
3
|
+
*
|
|
4
|
+
* Tracks request counts per key (typically IP address) within a sliding window.
|
|
5
|
+
* Periodically evicts expired entries to prevent unbounded memory growth.
|
|
6
|
+
*/
|
|
7
|
+
export declare class RateLimiter {
|
|
8
|
+
private readonly limits;
|
|
9
|
+
private readonly maxPerMinute;
|
|
10
|
+
private readonly windowMs;
|
|
11
|
+
private lastCleanup;
|
|
12
|
+
private static readonly CLEANUP_INTERVAL;
|
|
13
|
+
constructor(maxPerMinute: number, windowMs?: number);
|
|
14
|
+
/** Number of tracked entries (for monitoring/testing). */
|
|
15
|
+
get size(): number;
|
|
16
|
+
/** Check if a request from the given key is allowed. */
|
|
17
|
+
isAllowed(key: string): boolean;
|
|
18
|
+
/** Evict expired entries if enough time has passed since last cleanup. */
|
|
19
|
+
private maybeCleanup;
|
|
20
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relationship Population
|
|
3
|
+
*
|
|
4
|
+
* Populates relationship fields by replacing document IDs with actual
|
|
5
|
+
* related documents, up to a configurable depth level.
|
|
6
|
+
* Respects collection-level and field-level access control.
|
|
7
|
+
*/
|
|
8
|
+
import type { CollectionConfig, DatabaseAdapter, Field, RequestContext } from '@momentumcms/core';
|
|
9
|
+
export interface PopulateOptions {
|
|
10
|
+
/** Maximum depth of population (0 = no population, 1 = populate immediate, etc.) */
|
|
11
|
+
depth: number;
|
|
12
|
+
/** All collection configs (needed to resolve relationship targets) */
|
|
13
|
+
collections: CollectionConfig[];
|
|
14
|
+
/** Database adapter for fetching related documents */
|
|
15
|
+
adapter: DatabaseAdapter;
|
|
16
|
+
/** Request context for access control checks */
|
|
17
|
+
req?: RequestContext;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Populate relationship fields in a document up to the specified depth.
|
|
21
|
+
* Returns a new document with relationship IDs replaced by full documents.
|
|
22
|
+
*
|
|
23
|
+
* @param doc The document to populate
|
|
24
|
+
* @param fields The collection's field definitions
|
|
25
|
+
* @param options Population options including depth, collections, and adapter
|
|
26
|
+
*/
|
|
27
|
+
export declare function populateRelationships(doc: Record<string, unknown>, fields: Field[], options: PopulateOptions): Promise<Record<string, unknown>>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed Executor
|
|
3
|
+
*
|
|
4
|
+
* Main execution logic for the Momentum CMS seeding system.
|
|
5
|
+
* Handles processing seed entities, idempotency, and change detection.
|
|
6
|
+
*/
|
|
7
|
+
import type { DatabaseAdapter, SeedingConfig, SeededDocument } from '@momentumcms/core';
|
|
8
|
+
/**
|
|
9
|
+
* Minimal auth interface for seed executor.
|
|
10
|
+
* Avoids depending on the full auth package.
|
|
11
|
+
*/
|
|
12
|
+
export interface MomentumAuthLike {
|
|
13
|
+
api: {
|
|
14
|
+
signUpEmail: (options: {
|
|
15
|
+
body: {
|
|
16
|
+
name: string;
|
|
17
|
+
email: string;
|
|
18
|
+
password: string;
|
|
19
|
+
};
|
|
20
|
+
}) => Promise<{
|
|
21
|
+
user?: {
|
|
22
|
+
id: string;
|
|
23
|
+
} | null;
|
|
24
|
+
} | null>;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Result of a seeding run.
|
|
29
|
+
*/
|
|
30
|
+
export interface SeedingResult {
|
|
31
|
+
/**
|
|
32
|
+
* Total number of seed entities processed.
|
|
33
|
+
*/
|
|
34
|
+
total: number;
|
|
35
|
+
/**
|
|
36
|
+
* Number of new documents created.
|
|
37
|
+
*/
|
|
38
|
+
created: number;
|
|
39
|
+
/**
|
|
40
|
+
* Number of documents updated (data changed).
|
|
41
|
+
*/
|
|
42
|
+
updated: number;
|
|
43
|
+
/**
|
|
44
|
+
* Number of seeds skipped (already exist, no changes).
|
|
45
|
+
*/
|
|
46
|
+
skipped: number;
|
|
47
|
+
/**
|
|
48
|
+
* All seeded documents (for reference).
|
|
49
|
+
*/
|
|
50
|
+
seeds: SeededDocument[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Options for running the seeding process.
|
|
54
|
+
*/
|
|
55
|
+
export interface SeedingRunOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Optional auth instance for auth-aware user seeding.
|
|
58
|
+
* When provided, seeds with `syncAuth: true` will create Better Auth users
|
|
59
|
+
* with hashed passwords before creating the Momentum collection document.
|
|
60
|
+
*/
|
|
61
|
+
auth?: MomentumAuthLike;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Calculate SHA-256 checksum of seed data for change detection.
|
|
65
|
+
* Normalizes the JSON to ensure consistent checksums.
|
|
66
|
+
*
|
|
67
|
+
* @param data - The data to hash
|
|
68
|
+
* @returns SHA-256 hex string
|
|
69
|
+
*/
|
|
70
|
+
export declare function calculateChecksum(data: Record<string, unknown>): string;
|
|
71
|
+
/**
|
|
72
|
+
* Check if seeding should run based on configuration.
|
|
73
|
+
*
|
|
74
|
+
* @param runOnStart - The runOnStart option value
|
|
75
|
+
* @returns True if seeding should run
|
|
76
|
+
*/
|
|
77
|
+
export declare function shouldRunSeeding(runOnStart: boolean | 'development' | 'always'): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Run the seeding process.
|
|
80
|
+
*
|
|
81
|
+
* @param config - The seeding configuration
|
|
82
|
+
* @param adapter - The database adapter
|
|
83
|
+
* @param runOptions - Optional run options (e.g., auth instance for user sync)
|
|
84
|
+
* @returns Seeding result summary
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const result = await runSeeding(config.seeding, config.db.adapter, { auth });
|
|
89
|
+
* console.log(`Seeded ${result.created} new documents`);
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export declare function runSeeding(config: SeedingConfig, adapter: DatabaseAdapter, runOptions?: SeedingRunOptions): Promise<SeedingResult>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed Tracker
|
|
3
|
+
*
|
|
4
|
+
* Manages the internal seed tracking collection (_momentum_seeds).
|
|
5
|
+
* Tracks seeded entities to ensure idempotency across server restarts.
|
|
6
|
+
*/
|
|
7
|
+
import type { DatabaseAdapter } from '@momentumcms/core';
|
|
8
|
+
import type { SeedTrackingDocument } from '@momentumcms/core';
|
|
9
|
+
/**
|
|
10
|
+
* Data required to create a new seed tracking record.
|
|
11
|
+
*/
|
|
12
|
+
export interface CreateSeedTrackingData {
|
|
13
|
+
seedId: string;
|
|
14
|
+
collection: string;
|
|
15
|
+
documentId: string;
|
|
16
|
+
checksum: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Seed tracker interface for managing seed tracking records.
|
|
20
|
+
*/
|
|
21
|
+
export interface SeedTracker {
|
|
22
|
+
/**
|
|
23
|
+
* Find a seed tracking record by its seedId.
|
|
24
|
+
*
|
|
25
|
+
* @param seedId - The unique seed identifier
|
|
26
|
+
* @returns The tracking record or null if not found
|
|
27
|
+
*/
|
|
28
|
+
findBySeedId(seedId: string): Promise<SeedTrackingDocument | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Create a new seed tracking record.
|
|
31
|
+
*
|
|
32
|
+
* @param data - The tracking data
|
|
33
|
+
* @returns The created tracking record
|
|
34
|
+
*/
|
|
35
|
+
create(data: CreateSeedTrackingData): Promise<SeedTrackingDocument>;
|
|
36
|
+
/**
|
|
37
|
+
* Update the checksum of an existing seed tracking record.
|
|
38
|
+
*
|
|
39
|
+
* @param seedId - The unique seed identifier
|
|
40
|
+
* @param checksum - The new checksum
|
|
41
|
+
* @returns The updated tracking record
|
|
42
|
+
*/
|
|
43
|
+
updateChecksum(seedId: string, checksum: string): Promise<SeedTrackingDocument>;
|
|
44
|
+
/**
|
|
45
|
+
* Delete a seed tracking record by its seedId.
|
|
46
|
+
*
|
|
47
|
+
* @param seedId - The unique seed identifier
|
|
48
|
+
* @returns True if deleted, false if not found
|
|
49
|
+
*/
|
|
50
|
+
delete(seedId: string): Promise<boolean>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Creates a seed tracker instance for managing seed tracking records.
|
|
54
|
+
*
|
|
55
|
+
* @param adapter - The database adapter to use
|
|
56
|
+
* @returns Seed tracker instance
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const tracker = createSeedTracker(adapter);
|
|
61
|
+
* const existing = await tracker.findBySeedId('admin-user');
|
|
62
|
+
* if (!existing) {
|
|
63
|
+
* await tracker.create({
|
|
64
|
+
* seedId: 'admin-user',
|
|
65
|
+
* collection: 'user',
|
|
66
|
+
* documentId: 'uuid-here',
|
|
67
|
+
* checksum: 'sha256-hash',
|
|
68
|
+
* });
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare function createSeedTracker(adapter: DatabaseAdapter): SeedTracker;
|