@bernierllc/content-management-suite 0.4.2 → 0.7.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/server.js DELETED
@@ -1,1102 +0,0 @@
1
- #!/usr/bin/env node
2
- "use client";
3
- "use strict";
4
- var __create = Object.create;
5
- var __defProp = Object.defineProperty;
6
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
- var __getOwnPropNames = Object.getOwnPropertyNames;
8
- var __getProtoOf = Object.getPrototypeOf;
9
- var __hasOwnProp = Object.prototype.hasOwnProperty;
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
- // If the importer is in node compatibility mode or this is not an ESM
20
- // file that has been converted to a CommonJS file using a Babel-
21
- // compatible transform (i.e. "__esModule" has not been set), then set
22
- // "default" to the CommonJS "module.exports" for node compatibility.
23
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
- mod
25
- ));
26
-
27
- // src/types.ts
28
- var import_zod = require("zod");
29
- var ContentManagementConfigSchema = import_zod.z.object({
30
- // Server Configuration
31
- server: import_zod.z.object({
32
- port: import_zod.z.number().default(3e3),
33
- host: import_zod.z.string().default("localhost"),
34
- cors: import_zod.z.object({
35
- origin: import_zod.z.union([import_zod.z.string(), import_zod.z.array(import_zod.z.string())]).default("*"),
36
- credentials: import_zod.z.boolean().default(true)
37
- }).default({}),
38
- security: import_zod.z.object({
39
- helmet: import_zod.z.boolean().default(true),
40
- rateLimit: import_zod.z.object({
41
- enabled: import_zod.z.boolean().default(true),
42
- windowMs: import_zod.z.number().default(15 * 60 * 1e3),
43
- // 15 minutes
44
- max: import_zod.z.number().default(100)
45
- // limit each IP to 100 requests per windowMs
46
- }).default({})
47
- }).default({})
48
- }).default({}),
49
- // Database Configuration
50
- database: import_zod.z.object({
51
- type: import_zod.z.enum(["sqlite", "postgresql", "mysql", "mongodb"]).default("sqlite"),
52
- url: import_zod.z.string().optional(),
53
- host: import_zod.z.string().default("localhost"),
54
- port: import_zod.z.number().optional(),
55
- name: import_zod.z.string().default("content_management"),
56
- username: import_zod.z.string().optional(),
57
- password: import_zod.z.string().optional(),
58
- ssl: import_zod.z.boolean().default(false),
59
- pool: import_zod.z.object({
60
- min: import_zod.z.number().default(2),
61
- max: import_zod.z.number().default(10)
62
- }).default({})
63
- }).default({}),
64
- // Content Configuration
65
- content: import_zod.z.object({
66
- // Default editorial workflow
67
- defaultWorkflow: import_zod.z.object({
68
- id: import_zod.z.string().default("standard"),
69
- name: import_zod.z.string().default("Standard Workflow"),
70
- description: import_zod.z.string().default("Standard editorial workflow"),
71
- stages: import_zod.z.array(import_zod.z.object({
72
- id: import_zod.z.string(),
73
- name: import_zod.z.string(),
74
- order: import_zod.z.number(),
75
- isPublishStage: import_zod.z.boolean().default(false),
76
- allowsScheduling: import_zod.z.boolean().default(false),
77
- description: import_zod.z.string().optional(),
78
- permissions: import_zod.z.array(import_zod.z.string()).default([])
79
- })).default([
80
- {
81
- id: "write",
82
- name: "Write",
83
- order: 1,
84
- isPublishStage: false,
85
- allowsScheduling: false,
86
- description: "Write content",
87
- permissions: ["content.edit"]
88
- },
89
- {
90
- id: "publish",
91
- name: "Publish",
92
- order: 2,
93
- isPublishStage: true,
94
- allowsScheduling: true,
95
- description: "Publish content",
96
- permissions: ["content.publish"]
97
- }
98
- ]),
99
- transitions: import_zod.z.array(import_zod.z.object({
100
- id: import_zod.z.string(),
101
- from: import_zod.z.string(),
102
- to: import_zod.z.string(),
103
- description: import_zod.z.string().optional(),
104
- permissions: import_zod.z.array(import_zod.z.string()).default([])
105
- })).default([
106
- {
107
- id: "write-to-publish",
108
- from: "write",
109
- to: "publish",
110
- description: "Move from write to publish",
111
- permissions: ["content.publish"]
112
- }
113
- ])
114
- }).default({}),
115
- // Content types
116
- contentTypes: import_zod.z.array(import_zod.z.string()).default(["text", "image", "audio", "video"]),
117
- // Auto-save configuration
118
- autoSave: import_zod.z.object({
119
- enabled: import_zod.z.boolean().default(true),
120
- debounceMs: import_zod.z.number().default(1e3),
121
- maxRetries: import_zod.z.number().default(3),
122
- backoffMs: import_zod.z.number().default(1e3)
123
- }).default({}),
124
- // Soft delete configuration
125
- softDelete: import_zod.z.object({
126
- enabled: import_zod.z.boolean().default(true),
127
- showDeletedToUsers: import_zod.z.boolean().default(false),
128
- retentionDays: import_zod.z.number().default(30)
129
- }).default({}),
130
- // File upload configuration
131
- upload: import_zod.z.object({
132
- maxFileSize: import_zod.z.number().default(104857600),
133
- // 100MB
134
- allowedTypes: import_zod.z.array(import_zod.z.string()).default([
135
- "image/jpeg",
136
- "image/png",
137
- "image/webp",
138
- "image/gif",
139
- "audio/mpeg",
140
- "audio/wav",
141
- "audio/ogg",
142
- "video/mp4",
143
- "video/webm",
144
- "video/ogg"
145
- ]),
146
- storage: import_zod.z.object({
147
- type: import_zod.z.enum(["local", "s3", "gcs", "azure"]).default("local"),
148
- path: import_zod.z.string().default("./uploads"),
149
- bucket: import_zod.z.string().optional(),
150
- region: import_zod.z.string().optional(),
151
- accessKey: import_zod.z.string().optional(),
152
- secretKey: import_zod.z.string().optional()
153
- }).default({})
154
- }).default({})
155
- }).default({}),
156
- // UI Configuration
157
- ui: import_zod.z.object({
158
- theme: import_zod.z.object({
159
- mode: import_zod.z.enum(["light", "dark", "auto"]).default("auto"),
160
- primaryColor: import_zod.z.string().default("#007bff"),
161
- secondaryColor: import_zod.z.string().default("#6c757d"),
162
- accentColor: import_zod.z.string().default("#17a2b8")
163
- }).default({}),
164
- editor: import_zod.z.object({
165
- showToolbar: import_zod.z.boolean().default(true),
166
- showStatusBar: import_zod.z.boolean().default(true),
167
- showWordCount: import_zod.z.boolean().default(true),
168
- showCharacterCount: import_zod.z.boolean().default(true),
169
- autoSave: import_zod.z.boolean().default(true),
170
- placeholder: import_zod.z.string().default("Start writing your content...")
171
- }).default({}),
172
- list: import_zod.z.object({
173
- defaultView: import_zod.z.enum(["table", "list", "grid", "kanban"]).default("table"),
174
- pageSize: import_zod.z.number().default(20),
175
- showSearch: import_zod.z.boolean().default(true),
176
- showFilters: import_zod.z.boolean().default(true),
177
- showSorting: import_zod.z.boolean().default(true),
178
- showPagination: import_zod.z.boolean().default(true)
179
- }).default({})
180
- }).default({}),
181
- // Integration Configuration
182
- integrations: import_zod.z.object({
183
- neverAdmin: import_zod.z.object({
184
- enabled: import_zod.z.boolean().default(false),
185
- url: import_zod.z.string().optional(),
186
- apiKey: import_zod.z.string().optional(),
187
- syncInterval: import_zod.z.number().default(3e5)
188
- // 5 minutes
189
- }).default({}),
190
- neverHub: import_zod.z.object({
191
- enabled: import_zod.z.boolean().default(false),
192
- url: import_zod.z.string().optional(),
193
- apiKey: import_zod.z.string().optional(),
194
- packageDiscovery: import_zod.z.boolean().default(true)
195
- }).default({}),
196
- analytics: import_zod.z.object({
197
- enabled: import_zod.z.boolean().default(false),
198
- provider: import_zod.z.enum(["google", "mixpanel", "amplitude", "custom"]).optional(),
199
- trackingId: import_zod.z.string().optional(),
200
- config: import_zod.z.record(import_zod.z.any()).default({})
201
- }).default({})
202
- }).default({}),
203
- // Security Configuration
204
- security: import_zod.z.object({
205
- jwt: import_zod.z.object({
206
- secret: import_zod.z.string().default("your-secret-key"),
207
- expiresIn: import_zod.z.string().default("24h"),
208
- issuer: import_zod.z.string().default("content-management-suite")
209
- }).default({}),
210
- permissions: import_zod.z.object({
211
- enabled: import_zod.z.boolean().default(true),
212
- defaultRole: import_zod.z.string().default("user"),
213
- roles: import_zod.z.array(import_zod.z.object({
214
- name: import_zod.z.string(),
215
- permissions: import_zod.z.array(import_zod.z.string()),
216
- description: import_zod.z.string().optional()
217
- })).default([
218
- {
219
- name: "admin",
220
- permissions: ["*"],
221
- description: "Full administrative access"
222
- },
223
- {
224
- name: "editor",
225
- permissions: ["content.edit", "content.publish", "content.schedule"],
226
- description: "Content editing and publishing"
227
- },
228
- {
229
- name: "author",
230
- permissions: ["content.edit"],
231
- description: "Content creation and editing"
232
- },
233
- {
234
- name: "user",
235
- permissions: ["content.view"],
236
- description: "Content viewing only"
237
- }
238
- ])
239
- }).default({})
240
- }).default({}),
241
- // Logging Configuration
242
- logging: import_zod.z.object({
243
- level: import_zod.z.enum(["error", "warn", "info", "debug"]).default("info"),
244
- format: import_zod.z.enum(["json", "text"]).default("json"),
245
- file: import_zod.z.object({
246
- enabled: import_zod.z.boolean().default(true),
247
- path: import_zod.z.string().default("./logs"),
248
- maxSize: import_zod.z.string().default("10MB"),
249
- maxFiles: import_zod.z.number().default(5)
250
- }).default({}),
251
- console: import_zod.z.object({
252
- enabled: import_zod.z.boolean().default(true),
253
- colorize: import_zod.z.boolean().default(true)
254
- }).default({})
255
- }).default({}),
256
- // Performance Configuration
257
- performance: import_zod.z.object({
258
- cache: import_zod.z.object({
259
- enabled: import_zod.z.boolean().default(true),
260
- ttl: import_zod.z.number().default(300),
261
- // 5 minutes
262
- maxSize: import_zod.z.number().default(1e3)
263
- }).default({}),
264
- compression: import_zod.z.object({
265
- enabled: import_zod.z.boolean().default(true),
266
- level: import_zod.z.number().min(1).max(9).default(6)
267
- }).default({}),
268
- rateLimit: import_zod.z.object({
269
- enabled: import_zod.z.boolean().default(true),
270
- windowMs: import_zod.z.number().default(15 * 60 * 1e3),
271
- // 15 minutes
272
- max: import_zod.z.number().default(100)
273
- }).default({})
274
- }).default({})
275
- });
276
- var ContentManagementSuiteError = class extends Error {
277
- constructor(message, code, statusCode = 500, details) {
278
- super(message);
279
- this.name = "ContentManagementSuiteError";
280
- this.code = code;
281
- this.statusCode = statusCode;
282
- this.details = details;
283
- }
284
- };
285
- var ContentManagementSuiteValidationError = class extends ContentManagementSuiteError {
286
- constructor(message, details) {
287
- super(message, "VALIDATION_ERROR", 400, details);
288
- this.name = "ContentManagementSuiteValidationError";
289
- }
290
- };
291
- var ContentManagementSuiteNotFoundError = class extends ContentManagementSuiteError {
292
- constructor(message, details) {
293
- super(message, "NOT_FOUND", 404, details);
294
- this.name = "ContentManagementSuiteNotFoundError";
295
- }
296
- };
297
- var ContentManagementSuiteConflictError = class extends ContentManagementSuiteError {
298
- constructor(message, details) {
299
- super(message, "CONFLICT", 409, details);
300
- this.name = "ContentManagementSuiteConflictError";
301
- }
302
- };
303
- var ContentManagementSuiteInternalError = class extends ContentManagementSuiteError {
304
- constructor(message, details) {
305
- super(message, "INTERNAL_ERROR", 500, details);
306
- this.name = "ContentManagementSuiteInternalError";
307
- }
308
- };
309
-
310
- // src/index.ts
311
- var import_content_workflow_ui2 = require("@bernierllc/content-workflow-ui");
312
- var import_content_type_text2 = require("@bernierllc/content-type-text");
313
- var import_content_type_image2 = require("@bernierllc/content-type-image");
314
- var import_content_type_audio2 = require("@bernierllc/content-type-audio");
315
- var import_content_type_video2 = require("@bernierllc/content-type-video");
316
- var import_content_type_registry2 = require("@bernierllc/content-type-registry");
317
- var import_content_editorial_workflow = require("@bernierllc/content-editorial-workflow");
318
- var import_content_autosave_manager = require("@bernierllc/content-autosave-manager");
319
- var import_content_soft_delete = require("@bernierllc/content-soft-delete");
320
-
321
- // src/content-management-suite.ts
322
- var import_events = require("events");
323
- var import_express = __toESM(require("express"));
324
- var import_cors = __toESM(require("cors"));
325
- var import_helmet = __toESM(require("helmet"));
326
- var import_morgan = __toESM(require("morgan"));
327
- var import_compression = __toESM(require("compression"));
328
- var import_uuid = require("uuid");
329
- var import_content_type_registry = require("@bernierllc/content-type-registry");
330
- var import_content_type_text = require("@bernierllc/content-type-text");
331
- var import_content_type_image = require("@bernierllc/content-type-image");
332
- var import_content_type_audio = require("@bernierllc/content-type-audio");
333
- var import_content_type_video = require("@bernierllc/content-type-video");
334
- var import_content_workflow_ui = require("@bernierllc/content-workflow-ui");
335
- var ContentManagementSuiteImpl = class extends import_events.EventEmitter {
336
- constructor(options = {}) {
337
- super();
338
- // Stub until @bernierllc/content-editor-service is published
339
- this.autosaveManager = null;
340
- this.softDelete = null;
341
- this.workflowEngine = null;
342
- // Content Types
343
- this.contentTypes = /* @__PURE__ */ new Map();
344
- // Plugins and Middleware
345
- this.plugins = /* @__PURE__ */ new Map();
346
- this.middleware = [];
347
- this.hooks = /* @__PURE__ */ new Map();
348
- // State
349
- this.isStarted = false;
350
- this.isStopped = false;
351
- this.httpServer = null;
352
- this.options = options;
353
- this.config = this.loadConfiguration();
354
- this.contentTypeRegistry = new import_content_type_registry.ContentTypeRegistry();
355
- this.configManager = this.createConfigManagerStub();
356
- this.workflowService = this.createWorkflowServiceStub();
357
- this.editorService = this.createEditorServiceStub();
358
- this.workflow = {
359
- stepper: import_content_workflow_ui.WorkflowStepper,
360
- actions: import_content_workflow_ui.StageActionButtons,
361
- timeline: import_content_workflow_ui.WorkflowTimeline,
362
- admin: import_content_workflow_ui.WorkflowAdminConfig
363
- };
364
- this.server = (0, import_express.default)();
365
- this.setupMiddleware();
366
- this.setupRoutes();
367
- this.editor = this.createEditorStub();
368
- this.list = this.createListStub();
369
- this.registerDefaultContentTypes();
370
- if (options.plugins) {
371
- options.plugins.forEach((plugin) => this.registerPlugin(plugin));
372
- }
373
- }
374
- // Stub creators for services not yet published
375
- createConfigManagerStub() {
376
- return {
377
- getConfig: () => this.config,
378
- updateConfig: async (config2) => {
379
- this.config = { ...this.config, ...config2 };
380
- },
381
- start: async () => {
382
- },
383
- stop: async () => {
384
- }
385
- };
386
- }
387
- createWorkflowServiceStub() {
388
- return {
389
- listWorkflows: async () => [],
390
- getWorkflow: async (id) => ({ id, name: "Default Workflow" }),
391
- createWorkflow: async (data) => ({ id: (0, import_uuid.v4)(), ...data }),
392
- updateWorkflow: async (id, data) => ({ id, ...data }),
393
- deleteWorkflow: async (_id) => {
394
- },
395
- publishContent: async (id) => ({ id, status: "published" }),
396
- scheduleContent: async (id, date) => ({ id, scheduledFor: date }),
397
- unpublishContent: async (id) => ({ id, status: "draft" }),
398
- start: async () => {
399
- },
400
- stop: async () => {
401
- }
402
- };
403
- }
404
- createEditorServiceStub() {
405
- const contentStore = /* @__PURE__ */ new Map();
406
- return {
407
- listContent: async (_filters) => ({ items: Array.from(contentStore.values()), total: contentStore.size }),
408
- getContent: async (id) => contentStore.get(id) || null,
409
- createContent: async (type, data) => {
410
- const content = { id: (0, import_uuid.v4)(), type, ...data, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
411
- contentStore.set(content.id, content);
412
- return content;
413
- },
414
- updateContent: async (id, data) => {
415
- const existing = contentStore.get(id);
416
- if (!existing)
417
- throw new Error("Content not found");
418
- const updated = { ...existing, ...data, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
419
- contentStore.set(id, updated);
420
- return updated;
421
- },
422
- deleteContent: async (id, _soft) => {
423
- contentStore.delete(id);
424
- },
425
- start: async () => {
426
- },
427
- stop: async () => {
428
- }
429
- };
430
- }
431
- // Stub for editor interface (until @bernierllc/content-editor-ui is published)
432
- createEditorStub() {
433
- return {
434
- render: () => null,
435
- getValue: () => "",
436
- setValue: (_value) => {
437
- },
438
- focus: () => {
439
- },
440
- blur: () => {
441
- },
442
- on: (_event, _callback) => {
443
- },
444
- off: (_event, _callback) => {
445
- }
446
- };
447
- }
448
- // Stub for list interface (until @bernierllc/content-list-ui is published)
449
- createListStub() {
450
- return {
451
- render: () => null,
452
- getItems: () => [],
453
- setItems: (_items) => {
454
- },
455
- getSelectedItems: () => [],
456
- setSelectedItems: (_items) => {
457
- },
458
- on: (_event, _callback) => {
459
- },
460
- off: (_event, _callback) => {
461
- }
462
- };
463
- }
464
- loadConfiguration() {
465
- try {
466
- if (this.options.config) {
467
- return ContentManagementConfigSchema.parse(this.options.config);
468
- }
469
- const config2 = this.configManager?.getConfig() || {};
470
- return ContentManagementConfigSchema.parse(config2);
471
- } catch (error) {
472
- console.error("Failed to load configuration:", error);
473
- return ContentManagementConfigSchema.parse({});
474
- }
475
- }
476
- setupMiddleware() {
477
- if (this.config.server.security.helmet) {
478
- this.server.use((0, import_helmet.default)());
479
- }
480
- this.server.use((0, import_cors.default)(this.config.server.cors));
481
- if (this.config.performance.compression.enabled) {
482
- this.server.use((0, import_compression.default)({
483
- level: this.config.performance.compression.level
484
- }));
485
- }
486
- if (this.options.logger) {
487
- this.server.use((0, import_morgan.default)("combined", {
488
- stream: {
489
- write: (message) => {
490
- this.options.logger?.info(message.trim());
491
- }
492
- }
493
- }));
494
- }
495
- this.server.use(import_express.default.json({ limit: "10mb" }));
496
- this.server.use(import_express.default.urlencoded({ extended: true, limit: "10mb" }));
497
- this.middleware.sort((a, b) => (a.order || 0) - (b.order || 0)).forEach((middleware) => {
498
- this.server.use(middleware.handler);
499
- });
500
- }
501
- setupRoutes() {
502
- this.server.get("/health", (req, res) => {
503
- res.json({
504
- status: "healthy",
505
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
506
- version: "0.1.0",
507
- uptime: process.uptime()
508
- });
509
- });
510
- this.server.use("/api", this.createAPIRoutes());
511
- this.server.use("/admin", this.createAdminRoutes());
512
- this.server.use("/static", import_express.default.static("public"));
513
- this.server.use(this.errorHandler.bind(this));
514
- }
515
- createAPIRoutes() {
516
- const router = import_express.default.Router();
517
- router.get("/content", this.getContentList.bind(this));
518
- router.get("/content/:id", this.getContent.bind(this));
519
- router.post("/content", this.createContent.bind(this));
520
- router.put("/content/:id", this.updateContent.bind(this));
521
- router.delete("/content/:id", this.deleteContent.bind(this));
522
- router.post("/content/:id/publish", this.publishContent.bind(this));
523
- router.post("/content/:id/schedule", this.scheduleContent.bind(this));
524
- router.post("/content/:id/unpublish", this.unpublishContent.bind(this));
525
- router.get("/workflows", this.getWorkflows.bind(this));
526
- router.get("/workflows/:id", this.getWorkflow.bind(this));
527
- router.post("/workflows", this.createWorkflow.bind(this));
528
- router.put("/workflows/:id", this.updateWorkflow.bind(this));
529
- router.delete("/workflows/:id", this.deleteWorkflow.bind(this));
530
- router.get("/content-types", this.getContentTypes.bind(this));
531
- router.get("/content-types/:id", this.handleGetContentType.bind(this));
532
- router.post("/content-types", this.createContentType.bind(this));
533
- router.put("/content-types/:id", this.updateContentType.bind(this));
534
- router.delete("/content-types/:id", this.deleteContentType.bind(this));
535
- router.get("/config", this.handleGetConfig.bind(this));
536
- router.put("/config", this.handleUpdateConfig.bind(this));
537
- router.get("/users", this.getUsers.bind(this));
538
- router.get("/users/:id", this.getUser.bind(this));
539
- router.post("/users", this.createUser.bind(this));
540
- router.put("/users/:id", this.updateUser.bind(this));
541
- router.delete("/users/:id", this.deleteUser.bind(this));
542
- return router;
543
- }
544
- createAdminRoutes() {
545
- const router = import_express.default.Router();
546
- router.get("/", (req, res) => {
547
- res.json({
548
- message: "Content Management Suite Admin",
549
- version: "0.1.0",
550
- endpoints: [
551
- "/workflows",
552
- "/content-types",
553
- "/config",
554
- "/users"
555
- ]
556
- });
557
- });
558
- router.get("/workflows", this.getWorkflows.bind(this));
559
- router.post("/workflows", this.createWorkflow.bind(this));
560
- router.put("/workflows/:id", this.updateWorkflow.bind(this));
561
- router.delete("/workflows/:id", this.deleteWorkflow.bind(this));
562
- router.get("/content-types", this.getContentTypes.bind(this));
563
- router.post("/content-types", this.createContentType.bind(this));
564
- router.put("/content-types/:id", this.updateContentType.bind(this));
565
- router.delete("/content-types/:id", this.deleteContentType.bind(this));
566
- router.get("/config", this.handleGetConfig.bind(this));
567
- router.put("/config", this.handleUpdateConfig.bind(this));
568
- return router;
569
- }
570
- errorHandler(error, _req, res, _next) {
571
- this.emit("error", error);
572
- if (error instanceof ContentManagementSuiteError) {
573
- res.status(error.statusCode).json({
574
- error: {
575
- code: error.code,
576
- message: error.message,
577
- details: error.details
578
- }
579
- });
580
- } else {
581
- res.status(500).json({
582
- error: {
583
- code: "INTERNAL_ERROR",
584
- message: "An unexpected error occurred",
585
- details: process.env.NODE_ENV === "development" ? error.message : void 0
586
- }
587
- });
588
- }
589
- }
590
- registerDefaultContentTypes() {
591
- this.contentTypes.set("text", import_content_type_text.TextContentType);
592
- this.contentTypes.set("image", import_content_type_image.ImageContentType);
593
- this.contentTypes.set("audio", import_content_type_audio.AudioContentTypeManager);
594
- this.contentTypes.set("video", import_content_type_video.VideoContentType);
595
- }
596
- // Public API Methods
597
- async start() {
598
- if (this.isStarted) {
599
- throw new ContentManagementSuiteError("Suite is already started", "ALREADY_STARTED");
600
- }
601
- try {
602
- await this.configManager.start();
603
- await this.workflowService.start();
604
- await this.editorService.start();
605
- const port = this.config.server.port;
606
- const host = this.config.server.host;
607
- return new Promise((resolve, reject) => {
608
- this.httpServer = this.server.listen(port, host, () => {
609
- console.log(`Content Management Suite started on http://${host}:${port}`);
610
- this.isStarted = true;
611
- this.emit("started");
612
- resolve();
613
- });
614
- this.httpServer.on("error", (err) => {
615
- this.emit("error", err);
616
- reject(new ContentManagementSuiteInternalError("Failed to start server", err));
617
- });
618
- });
619
- } catch (error) {
620
- this.emit("error", error);
621
- throw new ContentManagementSuiteInternalError("Failed to start suite", error);
622
- }
623
- }
624
- async stop() {
625
- if (this.isStopped) {
626
- throw new ContentManagementSuiteError("Suite is already stopped", "ALREADY_STOPPED");
627
- }
628
- try {
629
- await this.configManager.stop();
630
- await this.workflowService.stop();
631
- await this.editorService.stop();
632
- if (this.httpServer) {
633
- return new Promise((resolve) => {
634
- this.httpServer.close(() => {
635
- console.log("Content Management Suite stopped");
636
- this.isStopped = true;
637
- this.emit("stopped");
638
- resolve();
639
- });
640
- });
641
- }
642
- this.isStopped = true;
643
- } catch (error) {
644
- this.emit("error", error);
645
- throw new ContentManagementSuiteInternalError("Failed to stop suite", error);
646
- }
647
- }
648
- getConfig() {
649
- return this.config;
650
- }
651
- async updateConfig(config2) {
652
- try {
653
- const newConfig = ContentManagementConfigSchema.parse({
654
- ...this.config,
655
- ...config2
656
- });
657
- this.config = newConfig;
658
- await this.configManager.updateConfig(newConfig);
659
- this.emit("config:updated", newConfig);
660
- } catch (error) {
661
- throw new ContentManagementSuiteValidationError("Invalid configuration", error);
662
- }
663
- }
664
- registerContentType(contentType) {
665
- const id = contentType?.id || contentType?.name || "unknown";
666
- this.contentTypes.set(id, contentType);
667
- this.emit("contentType:registered", contentType);
668
- }
669
- unregisterContentType(contentTypeId) {
670
- if (!this.contentTypes.has(contentTypeId)) {
671
- throw new ContentManagementSuiteNotFoundError("Content type not found");
672
- }
673
- this.contentTypes.delete(contentTypeId);
674
- this.emit("contentType:unregistered", contentTypeId);
675
- }
676
- getContentType(contentTypeId) {
677
- const contentType = this.contentTypes.get(contentTypeId);
678
- if (!contentType) {
679
- throw new ContentManagementSuiteNotFoundError("Content type not found");
680
- }
681
- return contentType;
682
- }
683
- listContentTypes() {
684
- return Array.from(this.contentTypes.entries()).map(([id, contentType]) => ({
685
- id,
686
- contentType,
687
- ...contentType
688
- }));
689
- }
690
- // Plugin Management
691
- registerPlugin(plugin) {
692
- if (this.plugins.has(plugin.name)) {
693
- throw new ContentManagementSuiteConflictError("Plugin already registered");
694
- }
695
- this.plugins.set(plugin.name, plugin);
696
- plugin.install(this);
697
- this.emit("plugin:registered", plugin);
698
- }
699
- unregisterPlugin(pluginName) {
700
- const plugin = this.plugins.get(pluginName);
701
- if (!plugin) {
702
- throw new ContentManagementSuiteNotFoundError("Plugin not found");
703
- }
704
- plugin.uninstall(this);
705
- this.plugins.delete(pluginName);
706
- this.emit("plugin:unregistered", pluginName);
707
- }
708
- // Middleware Management
709
- addMiddleware(middleware) {
710
- this.middleware.push(middleware);
711
- this.emit("middleware:added", middleware);
712
- }
713
- removeMiddleware(middlewareName) {
714
- const index = this.middleware.findIndex((m) => m.name === middlewareName);
715
- if (index === -1) {
716
- throw new ContentManagementSuiteNotFoundError("Middleware not found");
717
- }
718
- this.middleware.splice(index, 1);
719
- this.emit("middleware:removed", middlewareName);
720
- }
721
- // Hook Management
722
- addHook(hook) {
723
- if (!this.hooks.has(hook.name)) {
724
- this.hooks.set(hook.name, []);
725
- }
726
- this.hooks.get(hook.name).push(hook);
727
- this.hooks.get(hook.name).sort((a, b) => (a.priority || 0) - (b.priority || 0));
728
- this.emit("hook:added", hook);
729
- }
730
- removeHook(hookName, handler) {
731
- const hooks = this.hooks.get(hookName);
732
- if (!hooks) {
733
- throw new ContentManagementSuiteNotFoundError("Hook not found");
734
- }
735
- if (handler) {
736
- const index = hooks.findIndex((h) => h.handler === handler);
737
- if (index === -1) {
738
- throw new ContentManagementSuiteNotFoundError("Hook handler not found");
739
- }
740
- hooks.splice(index, 1);
741
- } else {
742
- this.hooks.delete(hookName);
743
- }
744
- this.emit("hook:removed", hookName);
745
- }
746
- // API Route Handlers
747
- async getContentList(req, res) {
748
- try {
749
- const { type, status, page = 1, limit = 20 } = req.query;
750
- const filters = { type, status, page: parseInt(page), limit: parseInt(limit) };
751
- const content = await this.editorService.listContent(filters);
752
- res.json(content);
753
- } catch (error) {
754
- throw new ContentManagementSuiteInternalError("Failed to get content list", error);
755
- }
756
- }
757
- async getContent(req, res) {
758
- try {
759
- const { id } = req.params;
760
- const content = await this.editorService.getContent(id);
761
- res.json(content);
762
- } catch (error) {
763
- throw new ContentManagementSuiteNotFoundError("Content not found", error);
764
- }
765
- }
766
- async createContent(req, res) {
767
- try {
768
- const { type, data } = req.body;
769
- const content = await this.editorService.createContent(type, data);
770
- this.emit("content:created", content);
771
- res.status(201).json(content);
772
- } catch (error) {
773
- throw new ContentManagementSuiteInternalError("Failed to create content", error);
774
- }
775
- }
776
- async updateContent(req, res) {
777
- try {
778
- const { id } = req.params;
779
- const { data } = req.body;
780
- const content = await this.editorService.updateContent(id, data);
781
- this.emit("content:updated", content);
782
- res.json(content);
783
- } catch (error) {
784
- throw new ContentManagementSuiteInternalError("Failed to update content", error);
785
- }
786
- }
787
- async deleteContent(req, res) {
788
- try {
789
- const { id } = req.params;
790
- const { soft = true } = req.query;
791
- await this.editorService.deleteContent(id, soft === "true");
792
- this.emit("content:deleted", { id });
793
- res.status(204).send();
794
- } catch (error) {
795
- throw new ContentManagementSuiteInternalError("Failed to delete content", error);
796
- }
797
- }
798
- async publishContent(req, res) {
799
- try {
800
- const { id } = req.params;
801
- const content = await this.workflowService.publishContent(id);
802
- this.emit("content:published", content);
803
- res.json(content);
804
- } catch (error) {
805
- throw new ContentManagementSuiteInternalError("Failed to publish content", error);
806
- }
807
- }
808
- async scheduleContent(req, res) {
809
- try {
810
- const { id } = req.params;
811
- const { date } = req.body;
812
- const content = await this.workflowService.scheduleContent(id, new Date(date));
813
- this.emit("content:scheduled", content, new Date(date));
814
- res.json(content);
815
- } catch (error) {
816
- throw new ContentManagementSuiteInternalError("Failed to schedule content", error);
817
- }
818
- }
819
- async unpublishContent(req, res) {
820
- try {
821
- const { id } = req.params;
822
- const content = await this.workflowService.unpublishContent(id);
823
- res.json(content);
824
- } catch (error) {
825
- throw new ContentManagementSuiteInternalError("Failed to unpublish content", error);
826
- }
827
- }
828
- async getWorkflows(req, res) {
829
- try {
830
- const workflows = await this.workflowService.listWorkflows();
831
- res.json(workflows);
832
- } catch (error) {
833
- throw new ContentManagementSuiteInternalError("Failed to get workflows", error);
834
- }
835
- }
836
- async getWorkflow(req, res) {
837
- try {
838
- const { id } = req.params;
839
- const workflow = await this.workflowService.getWorkflow(id);
840
- res.json(workflow);
841
- } catch (error) {
842
- throw new ContentManagementSuiteNotFoundError("Workflow not found", error);
843
- }
844
- }
845
- async createWorkflow(req, res) {
846
- try {
847
- const { data } = req.body;
848
- const workflow = await this.workflowService.createWorkflow(data);
849
- res.status(201).json(workflow);
850
- } catch (error) {
851
- throw new ContentManagementSuiteInternalError("Failed to create workflow", error);
852
- }
853
- }
854
- async updateWorkflow(req, res) {
855
- try {
856
- const { id } = req.params;
857
- const { data } = req.body;
858
- const workflow = await this.workflowService.updateWorkflow(id, data);
859
- res.json(workflow);
860
- } catch (error) {
861
- throw new ContentManagementSuiteInternalError("Failed to update workflow", error);
862
- }
863
- }
864
- async deleteWorkflow(req, res) {
865
- try {
866
- const { id } = req.params;
867
- await this.workflowService.deleteWorkflow(id);
868
- res.status(204).send();
869
- } catch (error) {
870
- throw new ContentManagementSuiteInternalError("Failed to delete workflow", error);
871
- }
872
- }
873
- async getContentTypes(req, res) {
874
- try {
875
- const contentTypes = this.listContentTypes();
876
- res.json(contentTypes);
877
- } catch (error) {
878
- throw new ContentManagementSuiteInternalError("Failed to get content types", error);
879
- }
880
- }
881
- async handleGetContentType(req, res) {
882
- try {
883
- const id = req.params.id;
884
- if (!id) {
885
- throw new ContentManagementSuiteNotFoundError("Content type ID required");
886
- }
887
- const contentType = this.contentTypes.get(id);
888
- if (!contentType) {
889
- throw new ContentManagementSuiteNotFoundError("Content type not found");
890
- }
891
- res.json(contentType);
892
- } catch (error) {
893
- throw new ContentManagementSuiteNotFoundError("Content type not found", error);
894
- }
895
- }
896
- async createContentType(req, res) {
897
- try {
898
- const { data } = req.body;
899
- this.registerContentType(data);
900
- res.status(201).json(data);
901
- } catch (error) {
902
- throw new ContentManagementSuiteInternalError("Failed to create content type", error);
903
- }
904
- }
905
- async updateContentType(req, res) {
906
- try {
907
- const id = req.params.id;
908
- if (!id) {
909
- throw new ContentManagementSuiteNotFoundError("Content type ID required");
910
- }
911
- const { data } = req.body;
912
- this.unregisterContentType(id);
913
- this.registerContentType(data);
914
- res.json(data);
915
- } catch (error) {
916
- throw new ContentManagementSuiteInternalError("Failed to update content type", error);
917
- }
918
- }
919
- async deleteContentType(req, res) {
920
- try {
921
- const id = req.params.id;
922
- if (!id) {
923
- throw new ContentManagementSuiteNotFoundError("Content type ID required");
924
- }
925
- this.unregisterContentType(id);
926
- res.status(204).send();
927
- } catch (error) {
928
- throw new ContentManagementSuiteInternalError("Failed to delete content type", error);
929
- }
930
- }
931
- async handleGetConfig(req, res) {
932
- try {
933
- res.json(this.config);
934
- } catch (error) {
935
- throw new ContentManagementSuiteInternalError("Failed to get config", error);
936
- }
937
- }
938
- async handleUpdateConfig(req, res) {
939
- try {
940
- const { config: config2 } = req.body;
941
- const newConfig = ContentManagementConfigSchema.parse({
942
- ...this.config,
943
- ...config2
944
- });
945
- this.config = newConfig;
946
- await this.configManager.updateConfig(newConfig);
947
- this.emit("config:updated", newConfig);
948
- res.json(this.config);
949
- } catch (error) {
950
- throw new ContentManagementSuiteValidationError("Invalid configuration", error);
951
- }
952
- }
953
- async getUsers(req, res) {
954
- try {
955
- res.json([]);
956
- } catch (error) {
957
- throw new ContentManagementSuiteInternalError("Failed to get users", error);
958
- }
959
- }
960
- async getUser(req, res) {
961
- try {
962
- const { id } = req.params;
963
- res.json({ id, name: "User" });
964
- } catch (error) {
965
- throw new ContentManagementSuiteNotFoundError("User not found", error);
966
- }
967
- }
968
- async createUser(req, res) {
969
- try {
970
- const { data } = req.body;
971
- res.status(201).json({ id: (0, import_uuid.v4)(), ...data });
972
- } catch (error) {
973
- throw new ContentManagementSuiteInternalError("Failed to create user", error);
974
- }
975
- }
976
- async updateUser(req, res) {
977
- try {
978
- const { id } = req.params;
979
- const { data } = req.body;
980
- res.json({ id, ...data });
981
- } catch (error) {
982
- throw new ContentManagementSuiteInternalError("Failed to update user", error);
983
- }
984
- }
985
- async deleteUser(req, res) {
986
- try {
987
- const { id: _id } = req.params;
988
- res.status(204).send();
989
- } catch (error) {
990
- throw new ContentManagementSuiteInternalError("Failed to delete user", error);
991
- }
992
- }
993
- };
994
- function createContentManagementSuite(options = {}) {
995
- return new ContentManagementSuiteImpl(options);
996
- }
997
-
998
- // src/server.ts
999
- var import_dotenv = require("dotenv");
1000
- (0, import_dotenv.config)();
1001
- async function main() {
1002
- try {
1003
- console.log("Starting Content Management Suite...");
1004
- const suite = createContentManagementSuite({
1005
- config: {
1006
- server: {
1007
- port: parseInt(process.env.CONTENT_MANAGEMENT_PORT || "3000"),
1008
- host: process.env.CONTENT_MANAGEMENT_HOST || "localhost",
1009
- cors: {
1010
- origin: process.env.CONTENT_MANAGEMENT_CORS_ORIGIN || "*",
1011
- credentials: true
1012
- },
1013
- security: {
1014
- helmet: true,
1015
- rateLimit: {
1016
- enabled: true,
1017
- windowMs: 15 * 60 * 1e3,
1018
- max: 100
1019
- }
1020
- }
1021
- },
1022
- database: {
1023
- type: process.env.CONTENT_MANAGEMENT_DATABASE_TYPE || "sqlite",
1024
- url: process.env.CONTENT_MANAGEMENT_DATABASE_URL,
1025
- host: process.env.CONTENT_MANAGEMENT_DATABASE_HOST || "localhost",
1026
- name: process.env.CONTENT_MANAGEMENT_DATABASE_NAME || "content_management",
1027
- ssl: process.env.CONTENT_MANAGEMENT_DATABASE_SSL === "true",
1028
- pool: {
1029
- min: 2,
1030
- max: 10
1031
- }
1032
- },
1033
- security: {
1034
- jwt: {
1035
- secret: process.env.CONTENT_MANAGEMENT_JWT_SECRET || "your-secret-key",
1036
- expiresIn: process.env.CONTENT_MANAGEMENT_JWT_EXPIRES_IN || "24h",
1037
- issuer: "content-management-suite"
1038
- },
1039
- permissions: {
1040
- enabled: true,
1041
- defaultRole: "user",
1042
- roles: [
1043
- { name: "admin", permissions: ["*"], description: "Full administrative access" },
1044
- { name: "editor", permissions: ["content.edit", "content.publish", "content.schedule"], description: "Content editing and publishing" },
1045
- { name: "author", permissions: ["content.edit"], description: "Content creation and editing" },
1046
- { name: "user", permissions: ["content.view"], description: "Content viewing only" }
1047
- ]
1048
- }
1049
- },
1050
- integrations: {
1051
- neverAdmin: {
1052
- enabled: process.env.CONTENT_MANAGEMENT_NEVERADMIN_ENABLED === "true",
1053
- url: process.env.CONTENT_MANAGEMENT_NEVERADMIN_URL,
1054
- apiKey: process.env.CONTENT_MANAGEMENT_NEVERADMIN_API_KEY,
1055
- syncInterval: 3e5
1056
- },
1057
- neverHub: {
1058
- enabled: process.env.CONTENT_MANAGEMENT_NEVERHUB_ENABLED === "true",
1059
- url: process.env.CONTENT_MANAGEMENT_NEVERHUB_URL,
1060
- apiKey: process.env.CONTENT_MANAGEMENT_NEVERHUB_API_KEY,
1061
- packageDiscovery: true
1062
- },
1063
- analytics: {
1064
- enabled: false,
1065
- config: {}
1066
- }
1067
- }
1068
- }
1069
- });
1070
- process.on("SIGINT", async () => {
1071
- console.log("\nReceived SIGINT, shutting down gracefully...");
1072
- try {
1073
- await suite.stop();
1074
- console.log("Suite stopped successfully");
1075
- process.exit(0);
1076
- } catch (error) {
1077
- console.error("Error during shutdown:", error);
1078
- process.exit(1);
1079
- }
1080
- });
1081
- process.on("SIGTERM", async () => {
1082
- console.log("\nReceived SIGTERM, shutting down gracefully...");
1083
- try {
1084
- await suite.stop();
1085
- console.log("Suite stopped successfully");
1086
- process.exit(0);
1087
- } catch (error) {
1088
- console.error("Error during shutdown:", error);
1089
- process.exit(1);
1090
- }
1091
- });
1092
- await suite.start();
1093
- console.log("Content Management Suite is running");
1094
- console.log(`Server: http://${process.env.CONTENT_MANAGEMENT_HOST || "localhost"}:${process.env.CONTENT_MANAGEMENT_PORT || "3000"}`);
1095
- console.log("Press Ctrl+C to stop");
1096
- } catch (error) {
1097
- console.error("Failed to start Content Management Suite:", error);
1098
- process.exit(1);
1099
- }
1100
- }
1101
- main();
1102
- //# sourceMappingURL=server.js.map