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