@azlib/cms 0.2.0 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/content/schema.ts","../src/core/config.ts","../src/core/hooks.ts","../src/core/options.ts","../src/content/lifecycle.ts","../src/content/revisions.ts","../src/content/slug.ts","../src/taxonomy/taxonomy.ts","../src/media/media-manager.ts","../src/auth/rbac.ts","../src/storage/memory-adapter.ts","../src/core/engine.ts","../src/api/router.ts","../src/client/cms-client.ts"],"sourcesContent":["/**\n * @azlib/cms - Declarative Content Schema DSL & Field Builders\n */\n\nimport type {\n CollectionConfig,\n FieldDefinition,\n SelectOption,\n} from \"../core/types.js\";\n\nexport interface TextFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n defaultValue?: string;\n unique?: boolean;\n min?: number;\n max?: number;\n pattern?: string;\n validate?: (\n value: string,\n data: Record<string, unknown>,\n ) => string | null | boolean;\n}\n\nexport interface SlugFieldOptions {\n name?: string;\n label?: string;\n from?: string;\n required?: boolean;\n unique?: boolean;\n}\n\nexport interface RichTextFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n defaultValue?: string;\n}\n\nexport interface NumberFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n defaultValue?: number;\n min?: number;\n max?: number;\n}\n\nexport interface BooleanFieldOptions {\n name: string;\n label?: string;\n description?: string;\n defaultValue?: boolean;\n}\n\nexport interface SelectFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n options: readonly (string | SelectOption)[];\n defaultValue?: string | number;\n}\n\nexport interface ImageFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n}\n\nexport interface TaxonomyFieldOptions {\n name: string;\n taxonomy: string;\n label?: string;\n required?: boolean;\n}\n\nexport interface RelationshipFieldOptions {\n name: string;\n targetCollection: string;\n label?: string;\n description?: string;\n required?: boolean;\n}\n\nexport interface DateFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n defaultValue?: string;\n}\n\nexport interface JsonFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n defaultValue?: unknown;\n}\n\nexport interface RepeaterFieldOptions {\n name: string;\n label?: string;\n description?: string;\n fields: readonly FieldDefinition[];\n min?: number;\n max?: number;\n}\n\nexport const fields = {\n text(options: TextFieldOptions): FieldDefinition<string> {\n return {\n type: \"text\",\n ...options,\n };\n },\n\n slug(options: SlugFieldOptions = {}): FieldDefinition<string> {\n return {\n name: options.name ?? \"slug\",\n type: \"slug\",\n label: options.label ?? \"Slug\",\n fromField: options.from ?? \"title\",\n required: options.required ?? false,\n unique: options.unique ?? true,\n };\n },\n\n richText(options: RichTextFieldOptions): FieldDefinition<string> {\n return {\n type: \"richText\",\n ...options,\n };\n },\n\n number(options: NumberFieldOptions): FieldDefinition<number> {\n return {\n type: \"number\",\n ...options,\n };\n },\n\n boolean(options: BooleanFieldOptions): FieldDefinition<boolean> {\n return {\n type: \"boolean\",\n defaultValue: false,\n ...options,\n };\n },\n\n select(options: SelectFieldOptions): FieldDefinition<string | number> {\n return {\n type: \"select\",\n ...options,\n };\n },\n\n image(options: ImageFieldOptions): FieldDefinition<string> {\n return {\n type: \"image\",\n ...options,\n };\n },\n\n taxonomy(options: TaxonomyFieldOptions): FieldDefinition<string | string[]> {\n return {\n type: \"taxonomy\",\n ...options,\n };\n },\n\n relationship(\n options: RelationshipFieldOptions,\n ): FieldDefinition<string | string[]> {\n return {\n type: \"relationship\",\n ...options,\n };\n },\n\n date(options: DateFieldOptions): FieldDefinition<string> {\n return {\n type: \"date\",\n ...options,\n };\n },\n\n json(options: JsonFieldOptions): FieldDefinition<unknown> {\n return {\n type: \"json\",\n ...options,\n };\n },\n\n repeater(\n options: RepeaterFieldOptions,\n ): FieldDefinition<Record<string, unknown>[]> {\n return {\n type: \"repeater\",\n ...options,\n };\n },\n};\n\nexport interface CollectionOptions {\n slug: string;\n label: string;\n singularLabel?: string;\n description?: string;\n hierarchical?: boolean;\n timestamps?: boolean;\n revisions?: boolean;\n draftable?: boolean;\n fields: readonly FieldDefinition[];\n taxonomies?: readonly string[];\n defaultSort?: {\n field: string;\n direction: \"asc\" | \"desc\";\n };\n}\n\n/**\n * Define a CMS Collection with field schemas and lifecycle rules.\n */\nexport function collection(options: CollectionOptions): CollectionConfig {\n return {\n slug: options.slug,\n label: options.label,\n singularLabel: options.singularLabel ?? options.label,\n description: options.description,\n hierarchical: options.hierarchical ?? false,\n timestamps: options.timestamps ?? true,\n revisions: options.revisions ?? true,\n draftable: options.draftable ?? true,\n fields: options.fields,\n taxonomies: options.taxonomies ?? [],\n defaultSort: options.defaultSort ?? {\n field: \"createdAt\",\n direction: \"desc\",\n },\n };\n}\n\n/**\n * Validate and apply default values to input data for a collection.\n */\nexport function validateAndNormalizeData(\n fieldsList: readonly FieldDefinition[],\n inputData: Record<string, unknown>,\n): { data: Record<string, unknown>; errors: Record<string, string> } {\n const normalized: Record<string, unknown> = { ...inputData };\n const errors: Record<string, string> = {};\n\n for (const field of fieldsList) {\n let val = normalized[field.name];\n\n // Apply default value if undefined\n if (val === undefined && field.defaultValue !== undefined) {\n val = field.defaultValue;\n normalized[field.name] = val;\n }\n\n // Required check\n if (field.required && (val === undefined || val === null || val === \"\")) {\n errors[field.name] = `${field.label || field.name} is required.`;\n continue;\n }\n\n // Type validation\n if (val !== undefined && val !== null) {\n if (field.type === \"number\" && typeof val !== \"number\") {\n const parsed = Number(val);\n if (Number.isNaN(parsed)) {\n errors[field.name] =\n `${field.label || field.name} must be a valid number.`;\n } else {\n normalized[field.name] = parsed;\n }\n } else if (field.type === \"boolean\" && typeof val !== \"boolean\") {\n normalized[field.name] = Boolean(val);\n }\n }\n\n // Custom validator\n if (field.validate && val !== undefined) {\n const res = field.validate(val, normalized);\n if (typeof res === \"string\") {\n errors[field.name] = res;\n } else if (res === false) {\n errors[field.name] = `${field.label || field.name} is invalid.`;\n }\n }\n }\n\n return { data: normalized, errors };\n}\n","/**\n * @azlib/cms - Configuration Definition & Normalization\n */\n\nimport type { CMSConfig, CollectionConfig } from \"./types.js\";\nimport { collection, fields } from \"../content/schema.js\";\n\n/**\n * Default standard collections provided when not explicitly specified.\n */\nexport const DEFAULT_COLLECTIONS: CollectionConfig[] = [\n collection({\n slug: \"posts\",\n label: \"Posts\",\n singularLabel: \"Post\",\n revisions: true,\n timestamps: true,\n taxonomies: [\"categories\", \"tags\"],\n fields: [\n fields.text({ name: \"title\", label: \"Title\", required: true }),\n fields.slug({ from: \"title\" }),\n fields.richText({ name: \"content\", label: \"Content\" }),\n fields.text({ name: \"excerpt\", label: \"Excerpt\" }),\n fields.image({ name: \"featuredImage\", label: \"Featured Image\" }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"draft\", \"pending_review\", \"scheduled\", \"published\", \"trash\"],\n defaultValue: \"draft\",\n }),\n ],\n }),\n collection({\n slug: \"pages\",\n label: \"Pages\",\n singularLabel: \"Page\",\n hierarchical: true,\n revisions: true,\n timestamps: true,\n fields: [\n fields.text({ name: \"title\", label: \"Title\", required: true }),\n fields.slug({ from: \"title\" }),\n fields.richText({ name: \"content\", label: \"Content\" }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"draft\", \"published\", \"trash\"],\n defaultValue: \"draft\",\n }),\n ],\n }),\n];\n\n/**\n * Type-safe configuration helper function for azlib.config.ts.\n */\nexport function defineConfig(config: CMSConfig): CMSConfig {\n return config;\n}\n\n/**\n * Normalize and merge user config with CMS defaults.\n */\nexport function normalizeConfig(config: Partial<CMSConfig>): CMSConfig {\n const collections =\n config.collections && config.collections.length > 0\n ? config.collections\n : DEFAULT_COLLECTIONS;\n\n return {\n site: {\n name: config.site?.name ?? \"Azlib CMS\",\n description:\n config.site?.description ?? \"A modern headless CMS powered by @azlib\",\n url: config.site?.url ?? \"http://localhost:3000\",\n locale: config.site?.locale ?? \"en-US\",\n timezone: config.site?.timezone ?? \"UTC\",\n ...config.site,\n },\n collections,\n taxonomies: config.taxonomies ?? [],\n admin: {\n route: config.admin?.route ?? \"/admin\",\n enableRegistration: config.admin?.enableRegistration ?? false,\n ...config.admin,\n },\n };\n}\n","/**\n * @azlib/cms - WordPress-style Action and Filter Hook System\n */\n\nexport type ActionCallback = (...args: unknown[]) => void | Promise<void>;\nexport type FilterCallback<T = unknown> = (\n value: T,\n ...args: unknown[]\n) => T | Promise<T>;\nexport type SyncFilterCallback<T = unknown> = (\n value: T,\n ...args: unknown[]\n) => T;\n\nexport interface HookEntry<TCallback> {\n readonly callback: TCallback;\n readonly priority: number;\n}\n\nexport class HooksManager {\n private actions = new Map<string, HookEntry<ActionCallback>[]>();\n private filters = new Map<string, HookEntry<FilterCallback<unknown>>[]>();\n\n /**\n * Register an action callback.\n * Lower priority numbers execute first (default: 10).\n */\n addAction(tag: string, callback: ActionCallback, priority = 10): this {\n const list = this.actions.get(tag) ?? [];\n list.push({ callback, priority });\n list.sort((a, b) => a.priority - b.priority);\n this.actions.set(tag, list);\n return this;\n }\n\n /**\n * Execute all callbacks registered for the specified action asynchronously.\n */\n async doAction(tag: string, ...args: unknown[]): Promise<void> {\n const list = this.actions.get(tag);\n if (!list || list.length === 0) return;\n\n for (const entry of list) {\n await entry.callback(...args);\n }\n }\n\n /**\n * Execute all callbacks registered for the specified action synchronously.\n */\n doActionSync(tag: string, ...args: unknown[]): void {\n const list = this.actions.get(tag);\n if (!list || list.length === 0) return;\n\n for (const entry of list) {\n const result = entry.callback(...args);\n if (result instanceof Promise) {\n // Run promise in background for sync calls\n result.catch((err) => {\n console.error(\n `[HooksManager] Unhandled error in async action '${tag}':`,\n err,\n );\n });\n }\n }\n }\n\n /**\n * Register a filter callback.\n * Filter callbacks receive a value and return the modified value.\n */\n addFilter<T = unknown>(\n tag: string,\n callback: FilterCallback<T>,\n priority = 10,\n ): this {\n const list = this.filters.get(tag) ?? [];\n list.push({ callback: callback as FilterCallback<unknown>, priority });\n list.sort((a, b) => a.priority - b.priority);\n this.filters.set(tag, list);\n return this;\n }\n\n /**\n * Apply all filters registered for the specified tag sequentially.\n */\n async applyFilters<T = unknown>(\n tag: string,\n initialValue: T,\n ...args: unknown[]\n ): Promise<T> {\n const list = this.filters.get(tag);\n if (!list || list.length === 0) return initialValue;\n\n let currentValue: unknown = initialValue;\n for (const entry of list) {\n currentValue = await entry.callback(currentValue, ...args);\n }\n return currentValue as T;\n }\n\n /**\n * Apply all filters registered for the specified tag synchronously.\n */\n applyFiltersSync<T = unknown>(\n tag: string,\n initialValue: T,\n ...args: unknown[]\n ): T {\n const list = this.filters.get(tag);\n if (!list || list.length === 0) return initialValue;\n\n let currentValue: unknown = initialValue;\n for (const entry of list) {\n const next = entry.callback(currentValue, ...args);\n if (next instanceof Promise) {\n throw new Error(\n `[HooksManager] Async filter detected during applyFiltersSync for tag '${tag}'. Use applyFilters instead.`,\n );\n }\n currentValue = next;\n }\n return currentValue as T;\n }\n\n /**\n * Remove a registered action callback.\n */\n removeAction(tag: string, callback: ActionCallback): boolean {\n const list = this.actions.get(tag);\n if (!list) return false;\n const initialLen = list.length;\n const filtered = list.filter((e) => e.callback !== callback);\n this.actions.set(tag, filtered);\n return filtered.length < initialLen;\n }\n\n /**\n * Remove a registered filter callback.\n */\n removeFilter<T = unknown>(tag: string, callback: FilterCallback<T>): boolean {\n const list = this.filters.get(tag);\n if (!list) return false;\n const initialLen = list.length;\n const filtered = list.filter((e) => (e.callback as unknown) !== callback);\n this.filters.set(tag, filtered);\n return filtered.length < initialLen;\n }\n\n /**\n * Check if any callbacks are registered for an action.\n */\n hasAction(tag: string): boolean {\n const list = this.actions.get(tag);\n return Boolean(list && list.length > 0);\n }\n\n /**\n * Check if any callbacks are registered for a filter.\n */\n hasFilter(tag: string): boolean {\n const list = this.filters.get(tag);\n return Boolean(list && list.length > 0);\n }\n\n /**\n * Remove all registered actions and filters.\n */\n removeAll(tag?: string): void {\n if (tag) {\n this.actions.delete(tag);\n this.filters.delete(tag);\n } else {\n this.actions.clear();\n this.filters.clear();\n }\n }\n}\n\nexport const defaultHooks = new HooksManager();\n","/**\n * @azlib/cms - Options & Settings Store\n */\n\nimport type { OptionItem } from \"./types.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { HooksManager } from \"./hooks.js\";\n\nexport class OptionsManager {\n constructor(\n private storage: CMSStorageAdapter,\n private hooks?: HooksManager,\n ) {}\n\n /**\n * Retrieve an option by key. Returns defaultValue if option does not exist.\n */\n async get<T = unknown>(\n key: string,\n defaultValue?: T,\n ): Promise<T | undefined> {\n const item = await this.storage.getOption<T>(key);\n let value = item ? item.value : defaultValue;\n\n if (this.hooks) {\n value = await this.hooks.applyFilters(`cms.option.${key}`, value);\n }\n\n return value;\n }\n\n /**\n * Set or update an option value.\n */\n async set<T = unknown>(\n key: string,\n value: T,\n options?: { autoload?: boolean; namespace?: string },\n ): Promise<OptionItem<T>> {\n let finalValue = value;\n if (this.hooks) {\n finalValue = await this.hooks.applyFilters(\n `cms.pre_set_option.${key}`,\n finalValue,\n );\n }\n\n const item: OptionItem<T> = {\n key,\n value: finalValue,\n autoload: options?.autoload ?? true,\n namespace: options?.namespace,\n updatedAt: new Date().toISOString(),\n };\n\n await this.storage.setOption(item);\n\n if (this.hooks) {\n await this.hooks.doAction(\"cms.option_updated\", key, finalValue);\n await this.hooks.doAction(`cms.option_updated.${key}`, finalValue);\n }\n\n return item;\n }\n\n /**\n * Delete an option by key.\n */\n async delete(key: string): Promise<boolean> {\n const deleted = await this.storage.deleteOption(key);\n if (deleted && this.hooks) {\n await this.hooks.doAction(\"cms.option_deleted\", key);\n }\n return deleted;\n }\n\n /**\n * Check if an option exists.\n */\n async has(key: string): Promise<boolean> {\n const item = await this.storage.getOption(key);\n return item !== null && item !== undefined;\n }\n\n /**\n * Get all options, optionally filtered by namespace.\n */\n async getAll(namespace?: string): Promise<Record<string, unknown>> {\n const items = await this.storage.getOptions(namespace);\n const result: Record<string, unknown> = {};\n for (const item of items) {\n result[item.key] = item.value;\n }\n return result;\n }\n}\n","/**\n * @azlib/cms - Content Lifecycle & Status Workflow Manager\n */\n\nimport type { ContentItem, ContentStatus } from \"../core/types.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { HooksManager } from \"../core/hooks.js\";\n\nexport const VALID_STATUS_TRANSITIONS: Record<\n ContentStatus,\n readonly ContentStatus[]\n> = {\n draft: [\"pending_review\", \"scheduled\", \"published\", \"private\", \"trash\"],\n pending_review: [\"draft\", \"scheduled\", \"published\", \"trash\"],\n scheduled: [\"draft\", \"published\", \"trash\"],\n published: [\"draft\", \"trash\", \"private\"],\n private: [\"draft\", \"published\", \"trash\"],\n trash: [\"draft\"],\n};\n\nexport class ContentLifecycle {\n constructor(\n private storage: CMSStorageAdapter,\n private hooks?: HooksManager,\n ) {}\n\n /**\n * Validate whether a status transition is permitted.\n */\n canTransition(\n currentStatus: ContentStatus,\n nextStatus: ContentStatus,\n ): boolean {\n if (currentStatus === nextStatus) return true;\n const allowed = VALID_STATUS_TRANSITIONS[currentStatus];\n return Boolean(allowed && allowed.includes(nextStatus));\n }\n\n /**\n * Process all scheduled content across a collection (or all collections) and publish mature items.\n */\n async processScheduledContent(\n collection: string,\n now: Date = new Date(),\n ): Promise<ContentItem[]> {\n const scheduledRes = await this.storage.findContent(collection, {\n status: \"scheduled\",\n limit: 1000,\n });\n\n const nowIso = now.toISOString();\n const publishedItems: ContentItem[] = [];\n\n for (const item of scheduledRes.items) {\n if (item.scheduledAt && item.scheduledAt <= nowIso) {\n const updated = await this.storage.updateContent(collection, item.id, {\n status: \"published\",\n publishedAt: item.scheduledAt,\n });\n\n if (updated) {\n publishedItems.push(updated);\n if (this.hooks) {\n await this.hooks.doAction(\"cms.content_published\", updated);\n await this.hooks.doAction(`cms.${collection}_published`, updated);\n }\n }\n }\n }\n\n return publishedItems;\n }\n}\n","/**\n * @azlib/cms - Content Revision History & Rollback Manager\n */\n\nimport type {\n ContentItem,\n RevisionDiff,\n RevisionDiffField,\n RevisionRecord,\n} from \"../core/types.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { HooksManager } from \"../core/hooks.js\";\n\nexport class RevisionManager {\n constructor(\n private storage: CMSStorageAdapter,\n private hooks?: HooksManager,\n ) {}\n\n /**\n * Save a revision snapshot for a content item.\n */\n async createRevision(\n item: ContentItem,\n authorId?: string | null,\n note?: string,\n ): Promise<RevisionRecord> {\n const revision = await this.storage.createRevision(\n item.id,\n item.collection,\n item.version,\n item,\n authorId,\n note,\n );\n\n if (this.hooks) {\n await this.hooks.doAction(\"cms.revision_created\", revision);\n }\n\n return revision;\n }\n\n /**\n * Get all revisions for a content item.\n */\n async getRevisions(contentId: string): Promise<RevisionRecord[]> {\n return this.storage.getRevisions(contentId);\n }\n\n /**\n * Get a specific revision by ID.\n */\n async getRevision(revisionId: string): Promise<RevisionRecord | null> {\n return this.storage.getRevision(revisionId);\n }\n\n /**\n * Compute differences between two content snapshots.\n */\n computeDiff(\n oldSnapshot: ContentItem,\n newSnapshot: ContentItem,\n ): RevisionDiff {\n const changes: RevisionDiffField[] = [];\n\n // Check title\n if (oldSnapshot.title !== newSnapshot.title) {\n changes.push({\n field: \"title\",\n oldValue: oldSnapshot.title,\n newValue: newSnapshot.title,\n });\n }\n\n // Check slug\n if (oldSnapshot.slug !== newSnapshot.slug) {\n changes.push({\n field: \"slug\",\n oldValue: oldSnapshot.slug,\n newValue: newSnapshot.slug,\n });\n }\n\n // Check status\n if (oldSnapshot.status !== newSnapshot.status) {\n changes.push({\n field: \"status\",\n oldValue: oldSnapshot.status,\n newValue: newSnapshot.status,\n });\n }\n\n // Check custom data fields (excluding already checked top-level fields)\n const allKeys = new Set([\n ...Object.keys(oldSnapshot.data || {}),\n ...Object.keys(newSnapshot.data || {}),\n ]);\n\n const topLevelFields = new Set([\"title\", \"slug\", \"status\"]);\n\n for (const key of allKeys) {\n if (topLevelFields.has(key)) continue;\n\n const oldVal = oldSnapshot.data?.[key];\n const newVal = newSnapshot.data?.[key];\n if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {\n changes.push({\n field: `data.${key}`,\n oldValue: oldVal,\n newValue: newVal,\n });\n }\n }\n\n return {\n contentId: newSnapshot.id,\n fromVersion: oldSnapshot.version,\n toVersion: newSnapshot.version,\n changes,\n };\n }\n\n /**\n * Restore a content item to a previous revision snapshot.\n */\n async restoreRevision(\n collection: string,\n revisionId: string,\n authorId?: string,\n ): Promise<ContentItem | null> {\n const revision = await this.storage.getRevision(revisionId);\n if (!revision || revision.collection !== collection) {\n return null;\n }\n\n const snapshot = revision.snapshot;\n\n const restored = await this.storage.updateContent(\n collection,\n revision.contentId,\n {\n title: snapshot.title,\n slug: snapshot.slug,\n status: snapshot.status,\n parentId: snapshot.parentId,\n data: snapshot.data,\n authorId: authorId ?? snapshot.authorId,\n },\n );\n\n if (restored) {\n // Create a new revision noting the restoration\n await this.createRevision(\n restored,\n authorId,\n `Restored from revision v${revision.version}`,\n );\n\n if (this.hooks) {\n await this.hooks.doAction(\"cms.revision_restored\", restored, revision);\n }\n }\n\n return restored;\n }\n}\n","/**\n * @azlib/cms - Slug generation and normalization utility\n */\n\n/**\n * Generate a clean, URL-safe slug from any input string.\n */\nexport function slugify(input: string): string {\n if (!input) return \"\";\n\n return input\n .toString()\n .normalize(\"NFKD\") // Normalize unicode accents\n .replace(/[\\u0300-\\u036f]/g, \"\") // Remove accent marks\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9\\s-_]/g, \"\") // Remove invalid characters\n .replace(/[\\s_-]+/g, \"-\") // Replace spaces, underscores, and multiple hyphens with single hyphen\n .replace(/^-+|-+$/g, \"\"); // Trim leading and trailing hyphens\n}\n\n/**\n * Create a unique slug given an existing set of slugs or a check function.\n */\nexport async function resolveUniqueSlug(\n baseSlug: string,\n isSlugTaken: (slug: string) => Promise<boolean> | boolean,\n currentId?: string,\n): Promise<string> {\n const root = slugify(baseSlug) || \"item\";\n let candidate = root;\n let counter = 1;\n\n while (await isSlugTaken(candidate)) {\n counter += 1;\n candidate = `${root}-${counter}`;\n }\n\n return candidate;\n}\n","/**\n * @azlib/cms - Taxonomy & Category/Tag Management\n */\n\nimport type { TaxonomyConfig, TermItem, TermTreeItem } from \"../core/types.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { HooksManager } from \"../core/hooks.js\";\nimport { resolveUniqueSlug, slugify } from \"../content/slug.js\";\n\nexport class TaxonomyManager {\n private registeredTaxonomies = new Map<string, TaxonomyConfig>();\n\n constructor(\n private storage: CMSStorageAdapter,\n private hooks?: HooksManager,\n ) {\n // Register default WordPress-like taxonomies\n this.registerTaxonomy({\n slug: \"categories\",\n label: \"Categories\",\n singularLabel: \"Category\",\n hierarchical: true,\n postTypes: [\"posts\"],\n });\n\n this.registerTaxonomy({\n slug: \"tags\",\n label: \"Tags\",\n singularLabel: \"Tag\",\n hierarchical: false,\n postTypes: [\"posts\"],\n });\n }\n\n /**\n * Register a taxonomy definition.\n */\n registerTaxonomy(config: TaxonomyConfig): void {\n this.registeredTaxonomies.set(config.slug, config);\n }\n\n /**\n * Get all registered taxonomies.\n */\n getTaxonomies(): TaxonomyConfig[] {\n return Array.from(this.registeredTaxonomies.values());\n }\n\n /**\n * Get a single taxonomy configuration by slug.\n */\n getTaxonomy(slug: string): TaxonomyConfig | undefined {\n return this.registeredTaxonomies.get(slug);\n }\n\n /**\n * Create a new term (e.g. category or tag).\n */\n async createTerm(\n taxonomy: string,\n data: {\n name: string;\n slug?: string;\n description?: string;\n parentId?: string | null;\n meta?: Record<string, unknown>;\n },\n ): Promise<TermItem> {\n const taxConfig = this.getTaxonomy(taxonomy);\n if (!taxConfig) {\n throw new Error(\n `[TaxonomyManager] Taxonomy '${taxonomy}' is not registered.`,\n );\n }\n\n const baseSlug = data.slug ? slugify(data.slug) : slugify(data.name);\n const finalSlug = await resolveUniqueSlug(baseSlug, async (s) => {\n const existing = await this.storage.getTermBySlug(taxonomy, s);\n return existing !== null;\n });\n\n const term = await this.storage.createTerm({\n taxonomy,\n name: data.name.trim(),\n slug: finalSlug,\n description: data.description,\n parentId: taxConfig.hierarchical ? (data.parentId ?? null) : null,\n meta: data.meta,\n });\n\n if (this.hooks) {\n await this.hooks.doAction(\"cms.term_created\", term);\n await this.hooks.doAction(`cms.${taxonomy}_term_created`, term);\n }\n\n return term;\n }\n\n /**\n * Get a term by ID.\n */\n async getTermById(id: string): Promise<TermItem | null> {\n return this.storage.getTermById(id);\n }\n\n /**\n * Get a term by slug within a taxonomy.\n */\n async getTermBySlug(\n taxonomy: string,\n slug: string,\n ): Promise<TermItem | null> {\n return this.storage.getTermBySlug(taxonomy, slug);\n }\n\n /**\n * Get terms for a taxonomy.\n */\n async getTerms(\n taxonomy: string,\n options?: { parentId?: string | null },\n ): Promise<TermItem[]> {\n return this.storage.getTerms(taxonomy, options);\n }\n\n /**\n * Build a hierarchical tree of terms for a taxonomy (parent -> children).\n */\n async getTermTree(taxonomy: string): Promise<TermTreeItem[]> {\n const allTerms = await this.storage.getTerms(taxonomy);\n const map = new Map<string, TermTreeItem>();\n const roots: TermTreeItem[] = [];\n\n // Initialize items with children arrays\n for (const term of allTerms) {\n map.set(term.id, { ...term, children: [] });\n }\n\n // Link parents and children\n for (const term of allTerms) {\n const node = map.get(term.id)!;\n if (term.parentId && map.has(term.parentId)) {\n map.get(term.parentId)!.children.push(node);\n } else {\n roots.push(node);\n }\n }\n\n return roots;\n }\n\n /**\n * Update a term.\n */\n async updateTerm(\n id: string,\n updates: {\n name?: string;\n slug?: string;\n description?: string;\n parentId?: string | null;\n meta?: Record<string, unknown>;\n },\n ): Promise<TermItem | null> {\n const existing = await this.storage.getTermById(id);\n if (!existing) return null;\n\n let slug = existing.slug;\n if (updates.slug && updates.slug !== existing.slug) {\n slug = await resolveUniqueSlug(\n updates.slug,\n async (s) => {\n const check = await this.storage.getTermBySlug(existing.taxonomy, s);\n return check !== null && check.id !== id;\n },\n id,\n );\n }\n\n const updated = await this.storage.updateTerm(id, {\n ...updates,\n slug,\n name: updates.name ? updates.name.trim() : existing.name,\n });\n\n if (updated && this.hooks) {\n await this.hooks.doAction(\"cms.term_updated\", updated);\n }\n\n return updated;\n }\n\n /**\n * Delete a term.\n */\n async deleteTerm(id: string): Promise<boolean> {\n const term = await this.storage.getTermById(id);\n if (!term) return false;\n\n const deleted = await this.storage.deleteTerm(id);\n if (deleted && this.hooks) {\n await this.hooks.doAction(\"cms.term_deleted\", term);\n }\n return deleted;\n }\n\n /**\n * Assign term IDs to a content item.\n */\n async assignTerms(contentId: string, termIds: string[]): Promise<void> {\n await this.storage.assignTermsToContent(contentId, termIds);\n if (this.hooks) {\n await this.hooks.doAction(\"cms.terms_assigned\", contentId, termIds);\n }\n }\n\n /**\n * Get all terms assigned to a content item.\n */\n async getContentTerms(\n contentId: string,\n taxonomy?: string,\n ): Promise<TermItem[]> {\n return this.storage.getContentTerms(contentId, taxonomy);\n }\n\n /**\n * Remove terms from a content item.\n */\n async removeTerms(contentId: string, termIds: string[]): Promise<void> {\n await this.storage.removeTermsFromContent(contentId, termIds);\n }\n}\n","/**\n * @azlib/cms - Media & Asset Management\n */\n\nimport type { MediaItem, PaginatedResult } from \"../core/types.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { HooksManager } from \"../core/hooks.js\";\nimport { slugify } from \"../content/slug.js\";\n\nexport interface MediaUploadInput {\n filename: string;\n mimeType: string;\n sizeBytes: number;\n url?: string;\n width?: number;\n height?: number;\n altText?: string;\n caption?: string;\n variants?: Record<string, string>;\n}\n\nexport class MediaManager {\n private allowedMimePrefixes = [\n \"image/\",\n \"video/\",\n \"audio/\",\n \"application/pdf\",\n \"text/\",\n ];\n\n constructor(\n private storage: CMSStorageAdapter,\n private hooks?: HooksManager,\n private publicBaseUrl = \"/uploads\",\n ) {}\n\n /**\n * Upload / register a new media item.\n */\n async upload(\n input: MediaUploadInput,\n authorId?: string | null,\n ): Promise<MediaItem> {\n // Validate MIME type\n const isAllowed = this.allowedMimePrefixes.some((prefix) =>\n input.mimeType.startsWith(prefix),\n );\n if (!isAllowed) {\n throw new Error(\n `[MediaManager] Unsupported MIME type: ${input.mimeType}`,\n );\n }\n\n // Clean filename\n const extMatch = input.filename.match(/\\.([a-zA-Z0-9]+)$/);\n const ext = extMatch ? `.${extMatch[1].toLowerCase()}` : \"\";\n const nameWithoutExt = input.filename.replace(/\\.[^/.]+$/, \"\");\n const cleanFilename = `${slugify(nameWithoutExt)}${ext}`;\n\n const url = input.url ?? `${this.publicBaseUrl}/${cleanFilename}`;\n\n const media = await this.storage.createMedia({\n filename: cleanFilename,\n originalName: input.filename,\n mimeType: input.mimeType,\n sizeBytes: input.sizeBytes,\n url,\n width: input.width,\n height: input.height,\n altText: input.altText,\n caption: input.caption,\n variants: input.variants,\n authorId,\n });\n\n if (this.hooks) {\n await this.hooks.doAction(\"cms.media_uploaded\", media);\n }\n\n return media;\n }\n\n /**\n * Get a media item by ID.\n */\n async get(id: string): Promise<MediaItem | null> {\n return this.storage.getMedia(id);\n }\n\n /**\n * Find media items.\n */\n async find(options?: {\n search?: string;\n mimeType?: string;\n authorId?: string;\n limit?: number;\n offset?: number;\n }): Promise<PaginatedResult<MediaItem>> {\n return this.storage.findMedia(options);\n }\n\n /**\n * Update media metadata (alt text, caption, dimensions).\n */\n async updateMetadata(\n id: string,\n updates: {\n altText?: string;\n caption?: string;\n width?: number;\n height?: number;\n },\n ): Promise<MediaItem | null> {\n const updated = await this.storage.updateMedia(id, updates);\n if (updated && this.hooks) {\n await this.hooks.doAction(\"cms.media_updated\", updated);\n }\n return updated;\n }\n\n /**\n * Delete a media item.\n */\n async delete(id: string): Promise<boolean> {\n const media = await this.storage.getMedia(id);\n if (!media) return false;\n\n const deleted = await this.storage.deleteMedia(id);\n if (deleted && this.hooks) {\n await this.hooks.doAction(\"cms.media_deleted\", media);\n }\n return deleted;\n }\n}\n","/**\n * @azlib/cms - Role-Based Access Control (RBAC) & Capabilities\n */\n\nimport type {\n CMSCapability,\n CMSUser,\n ContentItem,\n UserRole,\n} from \"../core/types.js\";\n\nexport const DEFAULT_ROLE_CAPABILITIES: Record<string, string[]> = {\n admin: [\n \"manage_options\",\n \"manage_taxonomies\",\n \"upload_files\",\n \"delete_files\",\n \"edit_posts\",\n \"edit_others_posts\",\n \"publish_posts\",\n \"delete_posts\",\n \"delete_others_posts\",\n \"read_private_posts\",\n ],\n editor: [\n \"manage_taxonomies\",\n \"upload_files\",\n \"delete_files\",\n \"edit_posts\",\n \"edit_others_posts\",\n \"publish_posts\",\n \"delete_posts\",\n \"delete_others_posts\",\n \"read_private_posts\",\n ],\n author: [\"upload_files\", \"edit_posts\", \"publish_posts\", \"delete_posts\"],\n contributor: [\"edit_posts\", \"delete_posts\"],\n subscriber: [\"read\"],\n};\n\nexport class RBACManager {\n private roleCapabilities = new Map<string, Set<string>>();\n\n constructor() {\n for (const [role, caps] of Object.entries(DEFAULT_ROLE_CAPABILITIES)) {\n this.roleCapabilities.set(role, new Set(caps));\n }\n }\n\n /**\n * Register a custom role with its capabilities.\n */\n registerRole(role: string, capabilities: string[]): void {\n this.roleCapabilities.set(role, new Set(capabilities));\n }\n\n /**\n * Add a capability to an existing role.\n */\n addCapabilityToRole(role: string, capability: string): void {\n let caps = this.roleCapabilities.get(role);\n if (!caps) {\n caps = new Set();\n this.roleCapabilities.set(role, caps);\n }\n caps.add(capability);\n }\n\n /**\n * Get all capabilities assigned to a role.\n */\n getRoleCapabilities(role: string): string[] {\n const caps = this.roleCapabilities.get(role);\n return caps ? Array.from(caps) : [];\n }\n\n /**\n * Check if a user possesses a specific capability.\n * If a target content item context is provided, checks object ownership rules.\n */\n can(\n user: CMSUser | null | undefined,\n capability: CMSCapability,\n context?: { contentItem?: ContentItem },\n ): boolean {\n if (!user || user.active === false) return false;\n\n // Check user-specific capability overrides\n if (user.capabilities && user.capabilities.includes(capability)) {\n return true;\n }\n\n const roleCaps = this.roleCapabilities.get(user.role);\n if (!roleCaps) return false;\n\n // Admin has full access\n if (user.role === \"admin\") return true;\n\n // Handle content item contextual checks (own vs others)\n if (context?.contentItem) {\n const isOwner = context.contentItem.authorId === user.id;\n\n if (capability === \"edit_posts\") {\n if (isOwner) {\n return roleCaps.has(\"edit_posts\");\n }\n return roleCaps.has(\"edit_others_posts\");\n }\n\n if (capability === \"delete_posts\") {\n if (isOwner) {\n return roleCaps.has(\"delete_posts\");\n }\n return roleCaps.has(\"delete_others_posts\");\n }\n }\n\n return roleCaps.has(capability);\n }\n}\n","/**\n * @azlib/cms - In-Memory Storage Adapter\n */\n\nimport type {\n ContentItem,\n ContentQueryOptions,\n MediaItem,\n OptionItem,\n PaginatedResult,\n RevisionRecord,\n TermItem,\n} from \"../core/types.js\";\nimport type { CMSStorageAdapter } from \"./storage-contract.js\";\n\nfunction generateId(prefix = \"\"): string {\n return `${prefix}${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 9)}`;\n}\n\nexport class MemoryStorageAdapter implements CMSStorageAdapter {\n private content = new Map<string, ContentItem>();\n private revisions = new Map<string, RevisionRecord>();\n private terms = new Map<string, TermItem>();\n private contentTerms = new Map<string, Set<string>>(); // contentId -> Set of termIds\n private media = new Map<string, MediaItem>();\n private options = new Map<string, OptionItem>();\n\n async init(): Promise<void> {}\n async close(): Promise<void> {}\n\n async createContent<T extends Record<string, unknown>>(\n item: Omit<ContentItem<T>, \"id\" | \"createdAt\" | \"updatedAt\" | \"version\">,\n ): Promise<ContentItem<T>> {\n const id = generateId(\"cnt_\");\n const now = new Date().toISOString();\n const fullItem: ContentItem<T> = {\n ...item,\n id,\n version: 1,\n createdAt: now,\n updatedAt: now,\n };\n this.content.set(id, fullItem as ContentItem);\n return JSON.parse(JSON.stringify(fullItem));\n }\n\n async getContent<T extends Record<string, unknown>>(\n collection: string,\n id: string,\n ): Promise<ContentItem<T> | null> {\n const item = this.content.get(id);\n if (!item || item.collection !== collection) return null;\n return JSON.parse(JSON.stringify(item)) as ContentItem<T>;\n }\n\n async getContentBySlug<T extends Record<string, unknown>>(\n collection: string,\n slug: string,\n ): Promise<ContentItem<T> | null> {\n for (const item of this.content.values()) {\n if (item.collection === collection && item.slug === slug) {\n return JSON.parse(JSON.stringify(item)) as ContentItem<T>;\n }\n }\n return null;\n }\n\n async findContent<T extends Record<string, unknown>>(\n collection: string,\n options: ContentQueryOptions = {},\n ): Promise<PaginatedResult<ContentItem<T>>> {\n let list: ContentItem[] = [];\n\n for (const item of this.content.values()) {\n if (item.collection !== collection) continue;\n\n // Status filter\n if (options.status) {\n const statuses = Array.isArray(options.status)\n ? options.status\n : [options.status];\n if (!statuses.includes(item.status)) continue;\n }\n\n // Author filter\n if (options.authorId && item.authorId !== options.authorId) continue;\n\n // Parent filter\n if (options.parentId !== undefined && item.parentId !== options.parentId)\n continue;\n\n // Term IDs filter\n if (options.termIds && options.termIds.length > 0) {\n const assigned = this.contentTerms.get(item.id);\n if (!assigned || !options.termIds.some((tId) => assigned.has(tId))) {\n continue;\n }\n }\n\n // Search\n if (options.search) {\n const query = options.search.toLowerCase();\n const inTitle = item.title?.toLowerCase().includes(query);\n const inSlug = item.slug.toLowerCase().includes(query);\n const inData = JSON.stringify(item.data).toLowerCase().includes(query);\n if (!inTitle && !inSlug && !inData) continue;\n }\n\n // Where matches\n if (options.where) {\n let match = true;\n for (const [key, val] of Object.entries(options.where)) {\n if (\n item.data[key] !== val &&\n (item as unknown as Record<string, unknown>)[key] !== val\n ) {\n match = false;\n break;\n }\n }\n if (!match) continue;\n }\n\n list.push(item);\n }\n\n const total = list.length;\n\n // Sorting\n const orderBy = options.orderBy || \"createdAt\";\n const dir = options.orderDirection === \"asc\" ? 1 : -1;\n\n list.sort((a, b) => {\n const valA =\n (a as unknown as Record<string, unknown>)[orderBy] ??\n a.data[orderBy] ??\n \"\";\n const valB =\n (b as unknown as Record<string, unknown>)[orderBy] ??\n b.data[orderBy] ??\n \"\";\n if (valA < valB) return -1 * dir;\n if (valA > valB) return 1 * dir;\n return 0;\n });\n\n // Pagination\n const offset = options.offset ?? 0;\n const limit = options.limit ?? 20;\n const paged = list.slice(offset, offset + limit);\n\n return {\n items: JSON.parse(JSON.stringify(paged)) as ContentItem<T>[],\n total,\n limit,\n offset,\n hasMore: offset + limit < total,\n };\n }\n\n async updateContent<T extends Record<string, unknown>>(\n collection: string,\n id: string,\n updates: Partial<Omit<ContentItem<T>, \"id\" | \"collection\" | \"createdAt\">>,\n ): Promise<ContentItem<T> | null> {\n const existing = this.content.get(id);\n if (!existing || existing.collection !== collection) return null;\n\n const updated: ContentItem = {\n ...existing,\n ...updates,\n data: {\n ...existing.data,\n ...(updates.data || {}),\n },\n version: existing.version + 1,\n updatedAt: new Date().toISOString(),\n };\n\n this.content.set(id, updated);\n return JSON.parse(JSON.stringify(updated)) as ContentItem<T>;\n }\n\n async deleteContent(collection: string, id: string): Promise<boolean> {\n const existing = this.content.get(id);\n if (!existing || existing.collection !== collection) return false;\n\n this.content.delete(id);\n this.contentTerms.delete(id);\n await this.deleteRevisionsByContentId(id);\n return true;\n }\n\n async countContent(\n collection: string,\n options: ContentQueryOptions = {},\n ): Promise<number> {\n const res = await this.findContent(collection, {\n ...options,\n limit: 1_000_000,\n });\n return res.total;\n }\n\n // Revisions\n async createRevision(\n contentId: string,\n collection: string,\n version: number,\n snapshot: ContentItem,\n authorId?: string | null,\n note?: string,\n ): Promise<RevisionRecord> {\n const id = generateId(\"rev_\");\n const record: RevisionRecord = {\n id,\n contentId,\n collection,\n version,\n snapshot: JSON.parse(JSON.stringify(snapshot)),\n authorId,\n note,\n createdAt: new Date().toISOString(),\n };\n this.revisions.set(id, record);\n return JSON.parse(JSON.stringify(record));\n }\n\n async getRevisions(contentId: string): Promise<RevisionRecord[]> {\n const list: RevisionRecord[] = [];\n for (const rev of this.revisions.values()) {\n if (rev.contentId === contentId) {\n list.push(rev);\n }\n }\n list.sort((a, b) => b.version - a.version);\n return JSON.parse(JSON.stringify(list));\n }\n\n async getRevision(revisionId: string): Promise<RevisionRecord | null> {\n const rev = this.revisions.get(revisionId);\n return rev ? JSON.parse(JSON.stringify(rev)) : null;\n }\n\n async deleteRevisionsByContentId(contentId: string): Promise<number> {\n let count = 0;\n for (const [id, rev] of this.revisions.entries()) {\n if (rev.contentId === contentId) {\n this.revisions.delete(id);\n count++;\n }\n }\n return count;\n }\n\n // Taxonomies & Terms\n async createTerm(\n term: Omit<TermItem, \"id\" | \"count\" | \"createdAt\" | \"updatedAt\">,\n ): Promise<TermItem> {\n const id = generateId(\"trm_\");\n const now = new Date().toISOString();\n const item: TermItem = {\n ...term,\n id,\n count: 0,\n createdAt: now,\n updatedAt: now,\n };\n this.terms.set(id, item);\n return JSON.parse(JSON.stringify(item));\n }\n\n async getTermById(id: string): Promise<TermItem | null> {\n const term = this.terms.get(id);\n return term ? JSON.parse(JSON.stringify(term)) : null;\n }\n\n async getTermBySlug(\n taxonomy: string,\n slug: string,\n ): Promise<TermItem | null> {\n for (const term of this.terms.values()) {\n if (term.taxonomy === taxonomy && term.slug === slug) {\n return JSON.parse(JSON.stringify(term));\n }\n }\n return null;\n }\n\n async getTerms(\n taxonomy: string,\n options?: { parentId?: string | null },\n ): Promise<TermItem[]> {\n const list: TermItem[] = [];\n for (const term of this.terms.values()) {\n if (term.taxonomy !== taxonomy) continue;\n if (options?.parentId !== undefined && term.parentId !== options.parentId)\n continue;\n list.push(term);\n }\n return JSON.parse(JSON.stringify(list));\n }\n\n async updateTerm(\n id: string,\n updates: Partial<Omit<TermItem, \"id\" | \"taxonomy\" | \"createdAt\">>,\n ): Promise<TermItem | null> {\n const term = this.terms.get(id);\n if (!term) return null;\n const updated: TermItem = {\n ...term,\n ...updates,\n updatedAt: new Date().toISOString(),\n };\n this.terms.set(id, updated);\n return JSON.parse(JSON.stringify(updated));\n }\n\n async deleteTerm(id: string): Promise<boolean> {\n const exists = this.terms.delete(id);\n if (exists) {\n for (const set of this.contentTerms.values()) {\n set.delete(id);\n }\n }\n return exists;\n }\n\n async assignTermsToContent(\n contentId: string,\n termIds: string[],\n ): Promise<void> {\n let set = this.contentTerms.get(contentId);\n if (!set) {\n set = new Set();\n this.contentTerms.set(contentId, set);\n }\n for (const id of termIds) {\n set.add(id);\n }\n this.recalculateTermCounts();\n }\n\n async getContentTerms(\n contentId: string,\n taxonomy?: string,\n ): Promise<TermItem[]> {\n const set = this.contentTerms.get(contentId);\n if (!set) return [];\n const list: TermItem[] = [];\n for (const termId of set) {\n const term = this.terms.get(termId);\n if (term) {\n if (!taxonomy || term.taxonomy === taxonomy) {\n list.push(term);\n }\n }\n }\n return JSON.parse(JSON.stringify(list));\n }\n\n async removeTermsFromContent(\n contentId: string,\n termIds: string[],\n ): Promise<void> {\n const set = this.contentTerms.get(contentId);\n if (!set) return;\n for (const id of termIds) {\n set.delete(id);\n }\n this.recalculateTermCounts();\n }\n\n private recalculateTermCounts(): void {\n const counts = new Map<string, number>();\n for (const set of this.contentTerms.values()) {\n for (const termId of set) {\n counts.set(termId, (counts.get(termId) || 0) + 1);\n }\n }\n for (const [id, term] of this.terms.entries()) {\n term.count = counts.get(id) || 0;\n }\n }\n\n // Media\n async createMedia(\n item: Omit<MediaItem, \"id\" | \"createdAt\" | \"updatedAt\">,\n ): Promise<MediaItem> {\n const id = generateId(\"med_\");\n const now = new Date().toISOString();\n const mediaItem: MediaItem = {\n ...item,\n id,\n createdAt: now,\n updatedAt: now,\n };\n this.media.set(id, mediaItem);\n return JSON.parse(JSON.stringify(mediaItem));\n }\n\n async getMedia(id: string): Promise<MediaItem | null> {\n const m = this.media.get(id);\n return m ? JSON.parse(JSON.stringify(m)) : null;\n }\n\n async findMedia(\n options: {\n search?: string;\n mimeType?: string;\n authorId?: string;\n limit?: number;\n offset?: number;\n } = {},\n ): Promise<PaginatedResult<MediaItem>> {\n const list: MediaItem[] = [];\n for (const item of this.media.values()) {\n if (options.mimeType && !item.mimeType.startsWith(options.mimeType))\n continue;\n if (options.authorId && item.authorId !== options.authorId) continue;\n if (options.search) {\n const q = options.search.toLowerCase();\n if (\n !item.filename.toLowerCase().includes(q) &&\n !item.originalName.toLowerCase().includes(q) &&\n !item.altText?.toLowerCase().includes(q)\n ) {\n continue;\n }\n }\n list.push(item);\n }\n\n list.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n const total = list.length;\n const offset = options.offset ?? 0;\n const limit = options.limit ?? 20;\n\n return {\n items: JSON.parse(JSON.stringify(list.slice(offset, offset + limit))),\n total,\n limit,\n offset,\n hasMore: offset + limit < total,\n };\n }\n\n async updateMedia(\n id: string,\n updates: Partial<Omit<MediaItem, \"id\" | \"createdAt\">>,\n ): Promise<MediaItem | null> {\n const m = this.media.get(id);\n if (!m) return null;\n const updated: MediaItem = {\n ...m,\n ...updates,\n updatedAt: new Date().toISOString(),\n };\n this.media.set(id, updated);\n return JSON.parse(JSON.stringify(updated));\n }\n\n async deleteMedia(id: string): Promise<boolean> {\n return this.media.delete(id);\n }\n\n // Options\n async getOption<T = unknown>(key: string): Promise<OptionItem<T> | null> {\n const opt = this.options.get(key);\n return opt ? (JSON.parse(JSON.stringify(opt)) as OptionItem<T>) : null;\n }\n\n async setOption<T = unknown>(item: OptionItem<T>): Promise<void> {\n this.options.set(item.key, JSON.parse(JSON.stringify(item)));\n }\n\n async deleteOption(key: string): Promise<boolean> {\n return this.options.delete(key);\n }\n\n async getOptions(namespace?: string): Promise<OptionItem[]> {\n const list: OptionItem[] = [];\n for (const opt of this.options.values()) {\n if (namespace && opt.namespace !== namespace) continue;\n list.push(opt);\n }\n return JSON.parse(JSON.stringify(list));\n }\n}\n","/**\n * @azlib/cms - Master CMS Engine Orchestrator\n */\n\nimport type {\n CMSConfig,\n CollectionConfig,\n ContentItem,\n ContentQueryOptions,\n PaginatedResult,\n RevisionDiff,\n RevisionRecord,\n} from \"./types.js\";\nimport { normalizeConfig } from \"./config.js\";\nimport { HooksManager } from \"./hooks.js\";\nimport { OptionsManager } from \"./options.js\";\nimport { ContentLifecycle } from \"../content/lifecycle.js\";\nimport { RevisionManager } from \"../content/revisions.js\";\nimport { validateAndNormalizeData } from \"../content/schema.js\";\nimport { resolveUniqueSlug, slugify } from \"../content/slug.js\";\nimport { TaxonomyManager } from \"../taxonomy/taxonomy.js\";\nimport { MediaManager } from \"../media/media-manager.js\";\nimport { RBACManager } from \"../auth/rbac.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport { MemoryStorageAdapter } from \"../storage/memory-adapter.js\";\n\nexport interface CreateContentInput {\n title?: string;\n slug?: string;\n status?: ContentItem[\"status\"];\n parentId?: string | null;\n scheduledAt?: string | null;\n data?: Record<string, unknown>;\n terms?: Record<string, string[]>;\n}\n\nexport interface UpdateContentInput {\n title?: string;\n slug?: string;\n status?: ContentItem[\"status\"];\n parentId?: string | null;\n scheduledAt?: string | null;\n data?: Record<string, unknown>;\n terms?: Record<string, string[]>;\n}\n\nexport interface CollectionService<\n TData extends Record<string, unknown> = Record<string, unknown>,\n> {\n readonly config: CollectionConfig;\n create(\n input: CreateContentInput,\n authorId?: string | null,\n ): Promise<ContentItem<TData>>;\n findById(id: string): Promise<ContentItem<TData> | null>;\n findBySlug(slug: string): Promise<ContentItem<TData> | null>;\n find(\n options?: ContentQueryOptions,\n ): Promise<PaginatedResult<ContentItem<TData>>>;\n update(\n id: string,\n input: UpdateContentInput,\n authorId?: string | null,\n revisionNote?: string,\n ): Promise<ContentItem<TData> | null>;\n delete(id: string): Promise<boolean>;\n publish(\n id: string,\n authorId?: string | null,\n ): Promise<ContentItem<TData> | null>;\n schedule(\n id: string,\n scheduledAt: Date | string,\n authorId?: string | null,\n ): Promise<ContentItem<TData> | null>;\n getRevisions(id: string): Promise<RevisionRecord[]>;\n getRevision(revisionId: string): Promise<RevisionRecord | null>;\n restoreRevision(\n id: string,\n revisionId: string,\n authorId?: string,\n ): Promise<ContentItem<TData> | null>;\n getDiff(\n oldVersion: ContentItem<TData>,\n newVersion: ContentItem<TData>,\n ): RevisionDiff;\n}\n\nexport class CMSEngine {\n readonly config: CMSConfig;\n readonly hooks: HooksManager;\n readonly storage: CMSStorageAdapter;\n readonly options: OptionsManager;\n readonly taxonomies: TaxonomyManager;\n readonly media: MediaManager;\n readonly rbac: RBACManager;\n readonly revisions: RevisionManager;\n readonly lifecycle: ContentLifecycle;\n\n private collections = new Map<string, CollectionConfig>();\n\n constructor(\n config: Partial<CMSConfig> = {},\n storage?: CMSStorageAdapter,\n hooks?: HooksManager,\n ) {\n this.config = normalizeConfig(config);\n this.hooks = hooks ?? new HooksManager();\n this.storage = storage ?? new MemoryStorageAdapter();\n\n this.options = new OptionsManager(this.storage, this.hooks);\n this.taxonomies = new TaxonomyManager(this.storage, this.hooks);\n this.media = new MediaManager(this.storage, this.hooks);\n this.rbac = new RBACManager();\n this.revisions = new RevisionManager(this.storage, this.hooks);\n this.lifecycle = new ContentLifecycle(this.storage, this.hooks);\n\n // Register collections from config\n for (const coll of this.config.collections) {\n this.collections.set(coll.slug, coll);\n }\n\n // Register taxonomies from config\n if (this.config.taxonomies) {\n for (const tax of this.config.taxonomies) {\n this.taxonomies.registerTaxonomy(tax);\n }\n }\n }\n\n /**\n * Initialize storage and trigger bootstrap hooks.\n */\n async init(): Promise<void> {\n await this.storage.init();\n\n // Populate initial site options if not already set\n if (this.config.site) {\n const hasTitle = await this.options.has(\"site_name\");\n if (!hasTitle) {\n await this.options.set(\"site_name\", this.config.site.name);\n }\n }\n\n await this.hooks.doAction(\"cms.init\", this);\n }\n\n /**\n * Close storage connections.\n */\n async close(): Promise<void> {\n await this.storage.close();\n await this.hooks.doAction(\"cms.close\", this);\n }\n\n /**\n * Get all registered collection configurations.\n */\n getCollections(): CollectionConfig[] {\n return Array.from(this.collections.values());\n }\n\n /**\n * Get a single collection configuration.\n */\n getCollectionConfig(slug: string): CollectionConfig | undefined {\n return this.collections.get(slug);\n }\n\n /**\n * Access high-level CRUD service for a collection.\n */\n collection<TData extends Record<string, unknown> = Record<string, unknown>>(\n slug: string,\n ): CollectionService<TData> {\n const collConfig = this.collections.get(slug);\n if (!collConfig) {\n throw new Error(`[CMSEngine] Collection '${slug}' is not registered.`);\n }\n\n const self = this;\n\n return {\n config: collConfig,\n\n async create(input, authorId = null) {\n const inputData: Record<string, unknown> = {\n ...(input.data || {}),\n };\n if (input.title !== undefined) inputData.title = input.title;\n if (input.slug !== undefined) inputData.slug = input.slug;\n if (input.status !== undefined) inputData.status = input.status;\n\n // Validate and normalize custom fields\n const { data: normalizedData, errors } = validateAndNormalizeData(\n collConfig.fields,\n inputData,\n );\n\n if (Object.keys(errors).length > 0) {\n throw new Error(\n `[CMSEngine] Validation failed for collection '${slug}': ${JSON.stringify(errors)}`,\n );\n }\n\n // Generate unique slug\n const title = (input.title ?? normalizedData.title ?? \"\") as string;\n const baseSlug = input.slug\n ? slugify(input.slug)\n : slugify(title) || \"item\";\n const finalSlug = await resolveUniqueSlug(baseSlug, async (s) => {\n const existing = await self.storage.getContentBySlug(slug, s);\n return existing !== null;\n });\n\n const status =\n input.status ?? (collConfig.draftable ? \"draft\" : \"published\");\n const nowIso = new Date().toISOString();\n\n // Create item\n const item = await self.storage.createContent<TData>({\n collection: slug,\n slug: finalSlug,\n title,\n status,\n parentId: collConfig.hierarchical ? (input.parentId ?? null) : null,\n authorId,\n publishedAt: status === \"published\" ? nowIso : null,\n scheduledAt:\n status === \"scheduled\" ? (input.scheduledAt ?? null) : null,\n data: normalizedData as TData,\n terms: input.terms,\n });\n\n // Assign terms if provided\n if (input.terms) {\n const allTermIds = Object.values(input.terms).flat();\n if (allTermIds.length > 0) {\n await self.taxonomies.assignTerms(item.id, allTermIds);\n }\n }\n\n // Create initial revision\n if (collConfig.revisions) {\n await self.revisions.createRevision(\n item,\n authorId,\n \"Initial creation\",\n );\n }\n\n await self.hooks.doAction(\"cms.content_created\", item);\n await self.hooks.doAction(`cms.${slug}_created`, item);\n\n return item;\n },\n\n async findById(id) {\n return self.storage.getContent<TData>(slug, id);\n },\n\n async findBySlug(contentSlug) {\n return self.storage.getContentBySlug<TData>(slug, contentSlug);\n },\n\n async find(options = {}) {\n return self.storage.findContent<TData>(slug, options);\n },\n\n async update(id, input, authorId = null, revisionNote) {\n const existing = await self.storage.getContent<TData>(slug, id);\n if (!existing) return null;\n\n const mergedData: Record<string, unknown> = {\n ...existing.data,\n ...(input.data || {}),\n };\n if (input.title !== undefined) mergedData.title = input.title;\n else if (existing.title !== undefined && mergedData.title === undefined)\n mergedData.title = existing.title;\n if (input.slug !== undefined) mergedData.slug = input.slug;\n else if (existing.slug !== undefined && mergedData.slug === undefined)\n mergedData.slug = existing.slug;\n if (input.status !== undefined) mergedData.status = input.status;\n else if (\n existing.status !== undefined &&\n mergedData.status === undefined\n )\n mergedData.status = existing.status;\n\n const { data: normalizedData, errors } = validateAndNormalizeData(\n collConfig.fields,\n mergedData,\n );\n\n if (Object.keys(errors).length > 0) {\n throw new Error(\n `[CMSEngine] Validation failed updating '${slug}': ${JSON.stringify(errors)}`,\n );\n }\n\n let updatedSlug = existing.slug;\n if (input.slug && input.slug !== existing.slug) {\n updatedSlug = await resolveUniqueSlug(\n input.slug,\n async (s) => {\n const check = await self.storage.getContentBySlug(slug, s);\n return check !== null && check.id !== id;\n },\n id,\n );\n }\n\n const nextStatus = input.status ?? existing.status;\n const nowIso = new Date().toISOString();\n let publishedAt = existing.publishedAt;\n if (nextStatus === \"published\" && !publishedAt) {\n publishedAt = nowIso;\n }\n\n const updated = await self.storage.updateContent<TData>(slug, id, {\n title: input.title !== undefined ? input.title : existing.title,\n slug: updatedSlug,\n status: nextStatus,\n parentId: collConfig.hierarchical\n ? input.parentId !== undefined\n ? input.parentId\n : existing.parentId\n : null,\n scheduledAt:\n input.scheduledAt !== undefined\n ? input.scheduledAt\n : existing.scheduledAt,\n publishedAt,\n authorId: authorId ?? existing.authorId,\n data: normalizedData as TData,\n terms: input.terms !== undefined ? input.terms : existing.terms,\n });\n\n if (updated) {\n // Update term associations if terms given\n if (input.terms) {\n const allTermIds = Object.values(input.terms).flat();\n await self.taxonomies.assignTerms(updated.id, allTermIds);\n }\n\n // Create revision snapshot\n if (collConfig.revisions) {\n await self.revisions.createRevision(\n updated,\n authorId,\n revisionNote ?? `Updated version ${updated.version}`,\n );\n }\n\n await self.hooks.doAction(\"cms.content_updated\", updated);\n await self.hooks.doAction(`cms.${slug}_updated`, updated);\n }\n\n return updated;\n },\n\n async delete(id) {\n const item = await self.storage.getContent(slug, id);\n if (!item) return false;\n\n const deleted = await self.storage.deleteContent(slug, id);\n if (deleted) {\n await self.hooks.doAction(\"cms.content_deleted\", item);\n await self.hooks.doAction(`cms.${slug}_deleted`, item);\n }\n return deleted;\n },\n\n async publish(id, authorId = null) {\n return this.update(\n id,\n { status: \"published\" },\n authorId,\n \"Published content\",\n );\n },\n\n async schedule(id, scheduledAt, authorId = null) {\n const dateStr =\n scheduledAt instanceof Date ? scheduledAt.toISOString() : scheduledAt;\n return this.update(\n id,\n { status: \"scheduled\", scheduledAt: dateStr },\n authorId,\n `Scheduled for publish at ${dateStr}`,\n );\n },\n\n async getRevisions(id) {\n return self.revisions.getRevisions(id);\n },\n\n async getRevision(revisionId) {\n return self.revisions.getRevision(revisionId);\n },\n\n async restoreRevision(id, revisionId, authorId) {\n return self.revisions.restoreRevision(\n slug,\n revisionId,\n authorId,\n ) as Promise<ContentItem<TData> | null>;\n },\n\n getDiff(oldVersion, newVersion) {\n return self.revisions.computeDiff(oldVersion, newVersion);\n },\n };\n }\n\n /**\n * Run scheduled content publisher for all registered collections.\n */\n async processScheduledContent(\n now: Date = new Date(),\n ): Promise<ContentItem[]> {\n const published: ContentItem[] = [];\n for (const coll of this.collections.values()) {\n const res = await this.lifecycle.processScheduledContent(coll.slug, now);\n published.push(...res);\n }\n return published;\n }\n}\n\n/**\n * Factory helper to create a configured CMSEngine instance.\n */\nexport function createCMSEngine(\n config?: Partial<CMSConfig>,\n storage?: CMSStorageAdapter,\n hooks?: HooksManager,\n): CMSEngine {\n return new CMSEngine(config, storage, hooks);\n}\n","/**\n * @azlib/cms - Universal Web Standard HTTP API Router (Request -> Response)\n */\n\nimport type { CMSEngine } from \"../core/engine.js\";\n\nfunction jsonResponse(\n data: unknown,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n ...headers,\n },\n });\n}\n\nexport class CMSRouter {\n constructor(private engine: CMSEngine) {}\n\n /**\n * Universal Web Standards request handler.\n */\n async handle(request: Request): Promise<Response> {\n const url = new URL(request.url);\n const pathname = url.pathname;\n const method = request.method.toUpperCase();\n\n // CORS preflight\n if (method === \"OPTIONS\") {\n return new Response(null, {\n status: 204,\n headers: {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n },\n });\n }\n\n try {\n // 1. Cron / Scheduled content runner: POST /api/cron/scheduled\n if (pathname === \"/api/cron/scheduled\" && method === \"POST\") {\n const published = await this.engine.processScheduledContent();\n return jsonResponse({\n success: true,\n publishedCount: published.length,\n items: published,\n });\n }\n\n // 2. Options API: /api/options(/.*)?\n if (pathname.startsWith(\"/api/options\")) {\n return this.handleOptions(pathname, method, url, request);\n }\n\n // 3. Taxonomies API: /api/taxonomies(/.*)?\n if (pathname.startsWith(\"/api/taxonomies\")) {\n return this.handleTaxonomies(pathname, method, url, request);\n }\n\n // 4. Media API: /api/media(/.*)?\n if (pathname.startsWith(\"/api/media\")) {\n return this.handleMedia(pathname, method, url, request);\n }\n\n // 5. Content API: /api/content/:collection(/.*)?\n if (pathname.startsWith(\"/api/content\")) {\n return this.handleContent(pathname, method, url, request);\n }\n\n // 404 Not Found for unmatched routes\n return jsonResponse({ error: \"Endpoint not found\", path: pathname }, 404);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return jsonResponse({ error: message }, 500);\n }\n }\n\n private async handleContent(\n pathname: string,\n method: string,\n url: URL,\n request: Request,\n ): Promise<Response> {\n const parts = pathname\n .replace(/^\\/api\\/content\\/?/, \"\")\n .split(\"/\")\n .filter(Boolean);\n const collectionSlug = parts[0];\n\n if (!collectionSlug) {\n return jsonResponse(\n {\n collections: this.engine.getCollections().map((c) => ({\n slug: c.slug,\n label: c.label,\n hierarchical: c.hierarchical,\n })),\n },\n 200,\n );\n }\n\n const coll = this.engine.collection(collectionSlug);\n\n // GET /api/content/:collection -> List\n if (parts.length === 1 && method === \"GET\") {\n const status = url.searchParams.get(\"status\") || undefined;\n const search = url.searchParams.get(\"search\") || undefined;\n const limit = url.searchParams.has(\"limit\")\n ? Number(url.searchParams.get(\"limit\"))\n : undefined;\n const offset = url.searchParams.has(\"offset\")\n ? Number(url.searchParams.get(\"offset\"))\n : undefined;\n const termIds = url.searchParams.has(\"termIds\")\n ? url.searchParams.get(\"termIds\")!.split(\",\")\n : undefined;\n\n const result = await coll.find({\n status: status as unknown as undefined,\n search,\n limit,\n offset,\n termIds,\n });\n\n return jsonResponse(result);\n }\n\n // POST /api/content/:collection -> Create\n if (parts.length === 1 && method === \"POST\") {\n const body = await request.json();\n const created = await coll.create(body);\n return jsonResponse(created, 201);\n }\n\n const idOrSlug = parts[1];\n\n // GET /api/content/:collection/:id/revisions\n if (parts.length === 3 && parts[2] === \"revisions\" && method === \"GET\") {\n const revs = await coll.getRevisions(idOrSlug);\n return jsonResponse(revs);\n }\n\n // POST /api/content/:collection/:id/restore/:revisionId\n if (parts.length === 4 && parts[2] === \"restore\" && method === \"POST\") {\n const revisionId = parts[3];\n const restored = await coll.restoreRevision(idOrSlug, revisionId);\n if (!restored) {\n return jsonResponse(\n { error: \"Revision or content item not found\" },\n 404,\n );\n }\n return jsonResponse(restored);\n }\n\n // GET /api/content/:collection/:idOrSlug\n if (parts.length === 2 && method === \"GET\") {\n const bySlug = url.searchParams.get(\"by\") === \"slug\";\n let item = bySlug\n ? await coll.findBySlug(idOrSlug)\n : await coll.findById(idOrSlug);\n if (!item && !bySlug) {\n // Fallback search by slug\n item = await coll.findBySlug(idOrSlug);\n }\n if (!item) return jsonResponse({ error: \"Content item not found\" }, 404);\n return jsonResponse(item);\n }\n\n // PUT /api/content/:collection/:id\n if (parts.length === 2 && method === \"PUT\") {\n const body = await request.json();\n const updated = await coll.update(idOrSlug, body);\n if (!updated)\n return jsonResponse({ error: \"Content item not found\" }, 404);\n return jsonResponse(updated);\n }\n\n // DELETE /api/content/:collection/:id\n if (parts.length === 2 && method === \"DELETE\") {\n const deleted = await coll.delete(idOrSlug);\n if (!deleted)\n return jsonResponse({ error: \"Content item not found\" }, 404);\n return jsonResponse({ success: true, id: idOrSlug });\n }\n\n return jsonResponse({ error: \"Method not allowed\" }, 405);\n }\n\n private async handleTaxonomies(\n pathname: string,\n method: string,\n url: URL,\n request: Request,\n ): Promise<Response> {\n const parts = pathname\n .replace(/^\\/api\\/taxonomies\\/?/, \"\")\n .split(\"/\")\n .filter(Boolean);\n\n // GET /api/taxonomies\n if (parts.length === 0 && method === \"GET\") {\n return jsonResponse(this.engine.taxonomies.getTaxonomies());\n }\n\n const taxonomySlug = parts[0];\n\n // GET /api/taxonomies/:taxonomy/terms\n if (parts.length === 2 && parts[1] === \"terms\" && method === \"GET\") {\n if (url.searchParams.get(\"tree\") === \"true\") {\n const tree = await this.engine.taxonomies.getTermTree(taxonomySlug);\n return jsonResponse(tree);\n }\n const terms = await this.engine.taxonomies.getTerms(taxonomySlug);\n return jsonResponse(terms);\n }\n\n // POST /api/taxonomies/:taxonomy/terms\n if (parts.length === 2 && parts[1] === \"terms\" && method === \"POST\") {\n const body = await request.json();\n const term = await this.engine.taxonomies.createTerm(taxonomySlug, body);\n return jsonResponse(term, 201);\n }\n\n // GET /api/taxonomies/:taxonomy/terms/:id\n if (parts.length === 3 && parts[1] === \"terms\" && method === \"GET\") {\n const term = await this.engine.taxonomies.getTermById(parts[2]);\n if (!term) return jsonResponse({ error: \"Term not found\" }, 404);\n return jsonResponse(term);\n }\n\n // PUT /api/taxonomies/:taxonomy/terms/:id\n if (parts.length === 3 && parts[1] === \"terms\" && method === \"PUT\") {\n const body = await request.json();\n const updated = await this.engine.taxonomies.updateTerm(parts[2], body);\n if (!updated) return jsonResponse({ error: \"Term not found\" }, 404);\n return jsonResponse(updated);\n }\n\n // DELETE /api/taxonomies/:taxonomy/terms/:id\n if (parts.length === 3 && parts[1] === \"terms\" && method === \"DELETE\") {\n const deleted = await this.engine.taxonomies.deleteTerm(parts[2]);\n if (!deleted) return jsonResponse({ error: \"Term not found\" }, 404);\n return jsonResponse({ success: true, id: parts[2] });\n }\n\n return jsonResponse({ error: \"Endpoint not found\" }, 404);\n }\n\n private async handleMedia(\n pathname: string,\n method: string,\n url: URL,\n request: Request,\n ): Promise<Response> {\n const parts = pathname\n .replace(/^\\/api\\/media\\/?/, \"\")\n .split(\"/\")\n .filter(Boolean);\n\n // GET /api/media\n if (parts.length === 0 && method === \"GET\") {\n const search = url.searchParams.get(\"search\") || undefined;\n const mimeType = url.searchParams.get(\"mimeType\") || undefined;\n const limit = url.searchParams.has(\"limit\")\n ? Number(url.searchParams.get(\"limit\"))\n : undefined;\n const offset = url.searchParams.has(\"offset\")\n ? Number(url.searchParams.get(\"offset\"))\n : undefined;\n\n const mediaList = await this.engine.media.find({\n search,\n mimeType,\n limit,\n offset,\n });\n return jsonResponse(mediaList);\n }\n\n // POST /api/media\n if (parts.length === 0 && method === \"POST\") {\n const body = await request.json();\n const media = await this.engine.media.upload(body);\n return jsonResponse(media, 201);\n }\n\n const id = parts[0];\n\n // GET /api/media/:id\n if (parts.length === 1 && method === \"GET\") {\n const media = await this.engine.media.get(id);\n if (!media) return jsonResponse({ error: \"Media not found\" }, 404);\n return jsonResponse(media);\n }\n\n // PUT /api/media/:id\n if (parts.length === 1 && method === \"PUT\") {\n const body = await request.json();\n const updated = await this.engine.media.updateMetadata(id, body);\n if (!updated) return jsonResponse({ error: \"Media not found\" }, 404);\n return jsonResponse(updated);\n }\n\n // DELETE /api/media/:id\n if (parts.length === 1 && method === \"DELETE\") {\n const deleted = await this.engine.media.delete(id);\n if (!deleted) return jsonResponse({ error: \"Media not found\" }, 404);\n return jsonResponse({ success: true, id });\n }\n\n return jsonResponse({ error: \"Method not allowed\" }, 405);\n }\n\n private async handleOptions(\n pathname: string,\n method: string,\n url: URL,\n request: Request,\n ): Promise<Response> {\n const key = pathname.replace(/^\\/api\\/options\\/?/, \"\");\n\n // GET /api/options\n if (!key && method === \"GET\") {\n const namespace = url.searchParams.get(\"namespace\") || undefined;\n const all = await this.engine.options.getAll(namespace);\n return jsonResponse(all);\n }\n\n // GET /api/options/:key\n if (key && method === \"GET\") {\n const val = await this.engine.options.get(key);\n if (val === undefined)\n return jsonResponse({ error: \"Option not found\" }, 404);\n return jsonResponse({ key, value: val });\n }\n\n // PUT /api/options/:key\n if (key && method === \"PUT\") {\n const body = await request.json();\n const item = await this.engine.options.set(key, body.value, {\n autoload: body.autoload,\n namespace: body.namespace,\n });\n return jsonResponse(item);\n }\n\n // DELETE /api/options/:key\n if (key && method === \"DELETE\") {\n const deleted = await this.engine.options.delete(key);\n if (!deleted) return jsonResponse({ error: \"Option not found\" }, 404);\n return jsonResponse({ success: true, key });\n }\n\n return jsonResponse({ error: \"Method not allowed\" }, 405);\n }\n}\n\nexport function createCMSRouter(engine: CMSEngine): CMSRouter {\n return new CMSRouter(engine);\n}\n","/**\n * @azlib/cms - Headless Client SDK\n */\n\nimport type { CMSEngine } from \"../core/engine.js\";\nimport type {\n ContentItem,\n ContentQueryOptions,\n MediaItem,\n PaginatedResult,\n TermItem,\n TermTreeItem,\n} from \"../core/types.js\";\n\nexport interface CMSClientOptions {\n engine?: CMSEngine;\n baseUrl?: string;\n fetch?: typeof globalThis.fetch;\n headers?: Record<string, string>;\n}\n\nexport interface ClientCollectionApi<\n TData extends Record<string, unknown> = Record<string, unknown>,\n> {\n find(\n options?: ContentQueryOptions,\n ): Promise<PaginatedResult<ContentItem<TData>>>;\n findById(id: string): Promise<ContentItem<TData> | null>;\n findBySlug(slug: string): Promise<ContentItem<TData> | null>;\n create(data: Record<string, unknown>): Promise<ContentItem<TData>>;\n update(\n id: string,\n data: Record<string, unknown>,\n ): Promise<ContentItem<TData> | null>;\n delete(id: string): Promise<boolean>;\n}\n\nexport class CMSClient {\n private engine?: CMSEngine;\n private baseUrl?: string;\n private fetchFn: typeof globalThis.fetch;\n private headers: Record<string, string>;\n\n constructor(options: CMSClientOptions) {\n this.engine = options.engine;\n this.baseUrl = options.baseUrl?.replace(/\\/+$/, \"\");\n this.fetchFn = options.fetch ?? globalThis.fetch?.bind(globalThis);\n this.headers = {\n \"Content-Type\": \"application/json\",\n ...(options.headers || {}),\n };\n }\n\n collection<TData extends Record<string, unknown> = Record<string, unknown>>(\n slug: string,\n ): ClientCollectionApi<TData> {\n const self = this;\n\n // Fast direct engine execution mode\n if (this.engine) {\n const coll = this.engine.collection<TData>(slug);\n return {\n find: (opts) => coll.find(opts),\n findById: (id) => coll.findById(id),\n findBySlug: (s) => coll.findBySlug(s),\n create: (data) => coll.create(data),\n update: (id, data) => coll.update(id, data),\n delete: (id) => coll.delete(id),\n };\n }\n\n // Remote HTTP fetch mode\n return {\n async find(options = {}) {\n const params = new URLSearchParams();\n if (options.status) {\n const statuses = Array.isArray(options.status)\n ? options.status.join(\",\")\n : options.status;\n params.set(\"status\", statuses);\n }\n if (options.search) params.set(\"search\", options.search);\n if (options.limit !== undefined)\n params.set(\"limit\", String(options.limit));\n if (options.offset !== undefined)\n params.set(\"offset\", String(options.offset));\n if (options.termIds && options.termIds.length > 0) {\n params.set(\"termIds\", options.termIds.join(\",\"));\n }\n\n const queryStr = params.toString() ? `?${params.toString()}` : \"\";\n return self.request<PaginatedResult<ContentItem<TData>>>(\n `/api/content/${slug}${queryStr}`,\n );\n },\n\n async findById(id: string) {\n return self.request<ContentItem<TData> | null>(\n `/api/content/${slug}/${id}`,\n );\n },\n\n async findBySlug(contentSlug: string) {\n return self.request<ContentItem<TData> | null>(\n `/api/content/${slug}/${contentSlug}?by=slug`,\n );\n },\n\n async create(data: Record<string, unknown>) {\n return self.request<ContentItem<TData>>(`/api/content/${slug}`, {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n },\n\n async update(id: string, data: Record<string, unknown>) {\n return self.request<ContentItem<TData> | null>(\n `/api/content/${slug}/${id}`,\n {\n method: \"PUT\",\n body: JSON.stringify(data),\n },\n );\n },\n\n async delete(id: string) {\n const res = await self.request<{ success: boolean }>(\n `/api/content/${slug}/${id}`,\n {\n method: \"DELETE\",\n },\n );\n return Boolean(res?.success);\n },\n };\n }\n\n readonly taxonomies = {\n getTerms: async (taxonomy: string): Promise<TermItem[]> => {\n if (this.engine) {\n return this.engine.taxonomies.getTerms(taxonomy);\n }\n return this.request<TermItem[]>(`/api/taxonomies/${taxonomy}/terms`);\n },\n\n getTree: async (taxonomy: string): Promise<TermTreeItem[]> => {\n if (this.engine) {\n return this.engine.taxonomies.getTermTree(taxonomy);\n }\n return this.request<TermTreeItem[]>(\n `/api/taxonomies/${taxonomy}/terms?tree=true`,\n );\n },\n };\n\n readonly media = {\n find: async (options?: {\n search?: string;\n limit?: number;\n }): Promise<PaginatedResult<MediaItem>> => {\n if (this.engine) {\n return this.engine.media.find(options);\n }\n const params = new URLSearchParams();\n if (options?.search) params.set(\"search\", options.search);\n if (options?.limit) params.set(\"limit\", String(options.limit));\n const q = params.toString() ? `?${params.toString()}` : \"\";\n return this.request<PaginatedResult<MediaItem>>(`/api/media${q}`);\n },\n\n get: async (id: string): Promise<MediaItem | null> => {\n if (this.engine) {\n return this.engine.media.get(id);\n }\n return this.request<MediaItem | null>(`/api/media/${id}`);\n },\n };\n\n readonly options = {\n get: async <T = unknown>(\n key: string,\n defaultValue?: T,\n ): Promise<T | undefined> => {\n if (this.engine) {\n return this.engine.options.get<T>(key, defaultValue);\n }\n try {\n const res = await this.request<{ key: string; value: T }>(\n `/api/options/${key}`,\n );\n return res?.value ?? defaultValue;\n } catch {\n return defaultValue;\n }\n },\n };\n\n private async request<T>(endpoint: string, init?: RequestInit): Promise<T> {\n if (!this.baseUrl) {\n throw new Error(\n `[CMSClient] baseUrl must be provided when connecting to a remote CMS API.`,\n );\n }\n const url = `${this.baseUrl}${endpoint}`;\n const res = await this.fetchFn(url, {\n ...init,\n headers: {\n ...this.headers,\n ...(init?.headers || {}),\n },\n });\n\n if (!res.ok) {\n if (res.status === 404) return null as unknown as T;\n const body = await res.text();\n throw new Error(`[CMSClient] HTTP ${res.status}: ${body}`);\n }\n\n return res.json() as Promise<T>;\n }\n}\n\nexport function createCmsClient(options: CMSClientOptions): CMSClient {\n return new CMSClient(options);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/content/schema.ts","../src/core/config.ts","../src/core/hooks.ts","../src/core/options.ts","../src/content/lifecycle.ts","../src/content/revisions.ts","../src/content/slug.ts","../src/taxonomy/taxonomy.ts","../src/media/media-manager.ts","../src/auth/rbac.ts","../src/storage/memory-adapter.ts","../src/core/engine.ts","../src/core/plugin.ts","../src/api/router.ts","../src/client/cms-client.ts"],"sourcesContent":["/**\n * @azlib/cms - Declarative Content Schema DSL & Field Builders\n */\n\nimport type {\n CollectionConfig,\n FieldDefinition,\n SelectOption,\n} from \"../core/types.js\";\n\nexport interface TextFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n defaultValue?: string;\n unique?: boolean;\n min?: number;\n max?: number;\n pattern?: string;\n validate?: (\n value: string,\n data: Record<string, unknown>,\n ) => string | null | boolean;\n}\n\nexport interface SlugFieldOptions {\n name?: string;\n label?: string;\n from?: string;\n required?: boolean;\n unique?: boolean;\n}\n\nexport interface RichTextFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n defaultValue?: string;\n}\n\nexport interface NumberFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n defaultValue?: number;\n min?: number;\n max?: number;\n}\n\nexport interface BooleanFieldOptions {\n name: string;\n label?: string;\n description?: string;\n defaultValue?: boolean;\n}\n\nexport interface SelectFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n options: readonly (string | SelectOption)[];\n defaultValue?: string | number;\n}\n\nexport interface ImageFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n}\n\nexport interface TaxonomyFieldOptions {\n name: string;\n taxonomy: string;\n label?: string;\n required?: boolean;\n}\n\nexport interface RelationshipFieldOptions {\n name: string;\n targetCollection: string;\n label?: string;\n description?: string;\n required?: boolean;\n}\n\nexport interface DateFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n defaultValue?: string;\n}\n\nexport interface JsonFieldOptions {\n name: string;\n label?: string;\n description?: string;\n required?: boolean;\n defaultValue?: unknown;\n}\n\nexport interface RepeaterFieldOptions {\n name: string;\n label?: string;\n description?: string;\n fields: readonly FieldDefinition[];\n min?: number;\n max?: number;\n}\n\nexport const fields = {\n text(options: TextFieldOptions): FieldDefinition<string> {\n return {\n type: \"text\",\n ...options,\n };\n },\n\n slug(options: SlugFieldOptions = {}): FieldDefinition<string> {\n return {\n name: options.name ?? \"slug\",\n type: \"slug\",\n label: options.label ?? \"Slug\",\n fromField: options.from ?? \"title\",\n required: options.required ?? false,\n unique: options.unique ?? true,\n };\n },\n\n richText(options: RichTextFieldOptions): FieldDefinition<string> {\n return {\n type: \"richText\",\n ...options,\n };\n },\n\n number(options: NumberFieldOptions): FieldDefinition<number> {\n return {\n type: \"number\",\n ...options,\n };\n },\n\n boolean(options: BooleanFieldOptions): FieldDefinition<boolean> {\n return {\n type: \"boolean\",\n defaultValue: false,\n ...options,\n };\n },\n\n select(options: SelectFieldOptions): FieldDefinition<string | number> {\n return {\n type: \"select\",\n ...options,\n };\n },\n\n image(options: ImageFieldOptions): FieldDefinition<string> {\n return {\n type: \"image\",\n ...options,\n };\n },\n\n taxonomy(options: TaxonomyFieldOptions): FieldDefinition<string | string[]> {\n return {\n type: \"taxonomy\",\n ...options,\n };\n },\n\n relationship(\n options: RelationshipFieldOptions,\n ): FieldDefinition<string | string[]> {\n return {\n type: \"relationship\",\n ...options,\n };\n },\n\n date(options: DateFieldOptions): FieldDefinition<string> {\n return {\n type: \"date\",\n ...options,\n };\n },\n\n json(options: JsonFieldOptions): FieldDefinition<unknown> {\n return {\n type: \"json\",\n ...options,\n };\n },\n\n repeater(\n options: RepeaterFieldOptions,\n ): FieldDefinition<Record<string, unknown>[]> {\n return {\n type: \"repeater\",\n ...options,\n };\n },\n};\n\nexport interface CollectionOptions {\n slug: string;\n label: string;\n singularLabel?: string;\n description?: string;\n hierarchical?: boolean;\n timestamps?: boolean;\n revisions?: boolean;\n draftable?: boolean;\n fields: readonly FieldDefinition[];\n taxonomies?: readonly string[];\n defaultSort?: {\n field: string;\n direction: \"asc\" | \"desc\";\n };\n}\n\n/**\n * Define a CMS Collection with field schemas and lifecycle rules.\n */\nexport function collection(options: CollectionOptions): CollectionConfig {\n return {\n slug: options.slug,\n label: options.label,\n singularLabel: options.singularLabel ?? options.label,\n description: options.description,\n hierarchical: options.hierarchical ?? false,\n timestamps: options.timestamps ?? true,\n revisions: options.revisions ?? true,\n draftable: options.draftable ?? true,\n fields: options.fields,\n taxonomies: options.taxonomies ?? [],\n defaultSort: options.defaultSort ?? {\n field: \"createdAt\",\n direction: \"desc\",\n },\n };\n}\n\n/**\n * Validate and apply default values to input data for a collection.\n */\nexport function validateAndNormalizeData(\n fieldsList: readonly FieldDefinition[],\n inputData: Record<string, unknown>,\n): { data: Record<string, unknown>; errors: Record<string, string> } {\n const normalized: Record<string, unknown> = { ...inputData };\n const errors: Record<string, string> = {};\n\n for (const field of fieldsList) {\n let val = normalized[field.name];\n\n // Apply default value if undefined\n if (val === undefined && field.defaultValue !== undefined) {\n val = field.defaultValue;\n normalized[field.name] = val;\n }\n\n // Required check\n if (field.required && (val === undefined || val === null || val === \"\")) {\n errors[field.name] = `${field.label || field.name} is required.`;\n continue;\n }\n\n // Type validation\n if (val !== undefined && val !== null) {\n if (field.type === \"number\" && typeof val !== \"number\") {\n const parsed = Number(val);\n if (Number.isNaN(parsed)) {\n errors[field.name] =\n `${field.label || field.name} must be a valid number.`;\n } else {\n normalized[field.name] = parsed;\n }\n } else if (field.type === \"boolean\" && typeof val !== \"boolean\") {\n normalized[field.name] = Boolean(val);\n }\n }\n\n // Custom validator\n if (field.validate && val !== undefined) {\n const res = field.validate(val, normalized);\n if (typeof res === \"string\") {\n errors[field.name] = res;\n } else if (res === false) {\n errors[field.name] = `${field.label || field.name} is invalid.`;\n }\n }\n }\n\n return { data: normalized, errors };\n}\n","/**\n * @azlib/cms - Configuration Definition & Normalization\n */\n\nimport type { CMSConfig, CollectionConfig } from \"./types.js\";\nimport { collection, fields } from \"../content/schema.js\";\n\n/**\n * Default standard collections provided when not explicitly specified.\n */\nexport const DEFAULT_COLLECTIONS: CollectionConfig[] = [\n collection({\n slug: \"posts\",\n label: \"Posts\",\n singularLabel: \"Post\",\n revisions: true,\n timestamps: true,\n taxonomies: [\"categories\", \"tags\"],\n fields: [\n fields.text({ name: \"title\", label: \"Title\", required: true }),\n fields.slug({ from: \"title\" }),\n fields.richText({ name: \"content\", label: \"Content\" }),\n fields.text({ name: \"excerpt\", label: \"Excerpt\" }),\n fields.image({ name: \"featuredImage\", label: \"Featured Image\" }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"draft\", \"pending_review\", \"scheduled\", \"published\", \"trash\"],\n defaultValue: \"draft\",\n }),\n ],\n }),\n collection({\n slug: \"pages\",\n label: \"Pages\",\n singularLabel: \"Page\",\n hierarchical: true,\n revisions: true,\n timestamps: true,\n fields: [\n fields.text({ name: \"title\", label: \"Title\", required: true }),\n fields.slug({ from: \"title\" }),\n fields.richText({ name: \"content\", label: \"Content\" }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"draft\", \"published\", \"trash\"],\n defaultValue: \"draft\",\n }),\n ],\n }),\n];\n\n/**\n * Type-safe configuration helper function for azlib.config.ts.\n */\nexport function defineConfig(config: CMSConfig): CMSConfig {\n return config;\n}\n\n/**\n * Normalize and merge user config with CMS defaults.\n */\nexport function normalizeConfig(config: Partial<CMSConfig>): CMSConfig {\n const collections =\n config.collections && config.collections.length > 0\n ? config.collections\n : DEFAULT_COLLECTIONS;\n\n return {\n site: {\n name: config.site?.name ?? \"Azlib CMS\",\n description:\n config.site?.description ?? \"A modern headless CMS powered by @azlib\",\n url: config.site?.url ?? \"http://localhost:3000\",\n locale: config.site?.locale ?? \"en-US\",\n timezone: config.site?.timezone ?? \"UTC\",\n ...config.site,\n },\n collections,\n taxonomies: config.taxonomies ?? [],\n plugins: config.plugins ?? [],\n admin: {\n route: config.admin?.route ?? \"/admin\",\n enableRegistration: config.admin?.enableRegistration ?? false,\n ...config.admin,\n },\n };\n}\n","/**\n * @azlib/cms - WordPress-style Action and Filter Hook System\n */\n\nexport type ActionCallback = (...args: unknown[]) => void | Promise<void>;\nexport type FilterCallback<T = unknown> = (\n value: T,\n ...args: unknown[]\n) => T | Promise<T>;\nexport type SyncFilterCallback<T = unknown> = (\n value: T,\n ...args: unknown[]\n) => T;\n\nexport interface HookEntry<TCallback> {\n readonly callback: TCallback;\n readonly priority: number;\n}\n\nexport class HooksManager {\n private actions = new Map<string, HookEntry<ActionCallback>[]>();\n private filters = new Map<string, HookEntry<FilterCallback<unknown>>[]>();\n\n /**\n * Register an action callback.\n * Lower priority numbers execute first (default: 10).\n */\n addAction(tag: string, callback: ActionCallback, priority = 10): this {\n const list = this.actions.get(tag) ?? [];\n list.push({ callback, priority });\n list.sort((a, b) => a.priority - b.priority);\n this.actions.set(tag, list);\n return this;\n }\n\n /**\n * Execute all callbacks registered for the specified action asynchronously.\n */\n async doAction(tag: string, ...args: unknown[]): Promise<void> {\n const list = this.actions.get(tag);\n if (!list || list.length === 0) return;\n\n for (const entry of list) {\n await entry.callback(...args);\n }\n }\n\n /**\n * Execute all callbacks registered for the specified action synchronously.\n */\n doActionSync(tag: string, ...args: unknown[]): void {\n const list = this.actions.get(tag);\n if (!list || list.length === 0) return;\n\n for (const entry of list) {\n const result = entry.callback(...args);\n if (result instanceof Promise) {\n // Run promise in background for sync calls\n result.catch((err) => {\n console.error(\n `[HooksManager] Unhandled error in async action '${tag}':`,\n err,\n );\n });\n }\n }\n }\n\n /**\n * Register a filter callback.\n * Filter callbacks receive a value and return the modified value.\n */\n addFilter<T = unknown>(\n tag: string,\n callback: FilterCallback<T>,\n priority = 10,\n ): this {\n const list = this.filters.get(tag) ?? [];\n list.push({ callback: callback as FilterCallback<unknown>, priority });\n list.sort((a, b) => a.priority - b.priority);\n this.filters.set(tag, list);\n return this;\n }\n\n /**\n * Apply all filters registered for the specified tag sequentially.\n */\n async applyFilters<T = unknown>(\n tag: string,\n initialValue: T,\n ...args: unknown[]\n ): Promise<T> {\n const list = this.filters.get(tag);\n if (!list || list.length === 0) return initialValue;\n\n let currentValue: unknown = initialValue;\n for (const entry of list) {\n currentValue = await entry.callback(currentValue, ...args);\n }\n return currentValue as T;\n }\n\n /**\n * Apply all filters registered for the specified tag synchronously.\n */\n applyFiltersSync<T = unknown>(\n tag: string,\n initialValue: T,\n ...args: unknown[]\n ): T {\n const list = this.filters.get(tag);\n if (!list || list.length === 0) return initialValue;\n\n let currentValue: unknown = initialValue;\n for (const entry of list) {\n const next = entry.callback(currentValue, ...args);\n if (next instanceof Promise) {\n throw new Error(\n `[HooksManager] Async filter detected during applyFiltersSync for tag '${tag}'. Use applyFilters instead.`,\n );\n }\n currentValue = next;\n }\n return currentValue as T;\n }\n\n /**\n * Remove a registered action callback.\n */\n removeAction(tag: string, callback: ActionCallback): boolean {\n const list = this.actions.get(tag);\n if (!list) return false;\n const initialLen = list.length;\n const filtered = list.filter((e) => e.callback !== callback);\n this.actions.set(tag, filtered);\n return filtered.length < initialLen;\n }\n\n /**\n * Remove a registered filter callback.\n */\n removeFilter<T = unknown>(tag: string, callback: FilterCallback<T>): boolean {\n const list = this.filters.get(tag);\n if (!list) return false;\n const initialLen = list.length;\n const filtered = list.filter((e) => (e.callback as unknown) !== callback);\n this.filters.set(tag, filtered);\n return filtered.length < initialLen;\n }\n\n /**\n * Check if any callbacks are registered for an action.\n */\n hasAction(tag: string): boolean {\n const list = this.actions.get(tag);\n return Boolean(list && list.length > 0);\n }\n\n /**\n * Check if any callbacks are registered for a filter.\n */\n hasFilter(tag: string): boolean {\n const list = this.filters.get(tag);\n return Boolean(list && list.length > 0);\n }\n\n /**\n * Remove all registered actions and filters.\n */\n removeAll(tag?: string): void {\n if (tag) {\n this.actions.delete(tag);\n this.filters.delete(tag);\n } else {\n this.actions.clear();\n this.filters.clear();\n }\n }\n}\n\nexport const defaultHooks = new HooksManager();\n","/**\n * @azlib/cms - Options & Settings Store\n */\n\nimport type { OptionItem } from \"./types.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { HooksManager } from \"./hooks.js\";\n\nexport class OptionsManager {\n constructor(\n private storage: CMSStorageAdapter,\n private hooks?: HooksManager,\n ) {}\n\n /**\n * Retrieve an option by key. Returns defaultValue if option does not exist.\n */\n async get<T = unknown>(\n key: string,\n defaultValue?: T,\n ): Promise<T | undefined> {\n const item = await this.storage.getOption<T>(key);\n let value = item ? item.value : defaultValue;\n\n if (this.hooks) {\n value = await this.hooks.applyFilters(`cms.option.${key}`, value);\n }\n\n return value;\n }\n\n /**\n * Set or update an option value.\n */\n async set<T = unknown>(\n key: string,\n value: T,\n options?: { autoload?: boolean; namespace?: string },\n ): Promise<OptionItem<T>> {\n let finalValue = value;\n if (this.hooks) {\n finalValue = await this.hooks.applyFilters(\n `cms.pre_set_option.${key}`,\n finalValue,\n );\n }\n\n const item: OptionItem<T> = {\n key,\n value: finalValue,\n autoload: options?.autoload ?? true,\n namespace: options?.namespace,\n updatedAt: new Date().toISOString(),\n };\n\n await this.storage.setOption(item);\n\n if (this.hooks) {\n await this.hooks.doAction(\"cms.option_updated\", key, finalValue);\n await this.hooks.doAction(`cms.option_updated.${key}`, finalValue);\n }\n\n return item;\n }\n\n /**\n * Delete an option by key.\n */\n async delete(key: string): Promise<boolean> {\n const deleted = await this.storage.deleteOption(key);\n if (deleted && this.hooks) {\n await this.hooks.doAction(\"cms.option_deleted\", key);\n }\n return deleted;\n }\n\n /**\n * Check if an option exists.\n */\n async has(key: string): Promise<boolean> {\n const item = await this.storage.getOption(key);\n return item !== null && item !== undefined;\n }\n\n /**\n * Get all options, optionally filtered by namespace.\n */\n async getAll(namespace?: string): Promise<Record<string, unknown>> {\n const items = await this.storage.getOptions(namespace);\n const result: Record<string, unknown> = {};\n for (const item of items) {\n result[item.key] = item.value;\n }\n return result;\n }\n}\n","/**\n * @azlib/cms - Content Lifecycle & Status Workflow Manager\n */\n\nimport type { ContentItem, ContentStatus } from \"../core/types.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { HooksManager } from \"../core/hooks.js\";\n\nexport const VALID_STATUS_TRANSITIONS: Record<\n ContentStatus,\n readonly ContentStatus[]\n> = {\n draft: [\"pending_review\", \"scheduled\", \"published\", \"private\", \"trash\"],\n pending_review: [\"draft\", \"scheduled\", \"published\", \"trash\"],\n scheduled: [\"draft\", \"published\", \"trash\"],\n published: [\"draft\", \"trash\", \"private\"],\n private: [\"draft\", \"published\", \"trash\"],\n trash: [\"draft\"],\n};\n\nexport class ContentLifecycle {\n constructor(\n private storage: CMSStorageAdapter,\n private hooks?: HooksManager,\n ) {}\n\n /**\n * Validate whether a status transition is permitted.\n */\n canTransition(\n currentStatus: ContentStatus,\n nextStatus: ContentStatus,\n ): boolean {\n if (currentStatus === nextStatus) return true;\n const allowed = VALID_STATUS_TRANSITIONS[currentStatus];\n return Boolean(allowed && allowed.includes(nextStatus));\n }\n\n /**\n * Process all scheduled content across a collection (or all collections) and publish mature items.\n */\n async processScheduledContent(\n collection: string,\n now: Date = new Date(),\n ): Promise<ContentItem[]> {\n const scheduledRes = await this.storage.findContent(collection, {\n status: \"scheduled\",\n limit: 1000,\n });\n\n const nowIso = now.toISOString();\n const publishedItems: ContentItem[] = [];\n\n for (const item of scheduledRes.items) {\n if (item.scheduledAt && item.scheduledAt <= nowIso) {\n const updated = await this.storage.updateContent(collection, item.id, {\n status: \"published\",\n publishedAt: item.scheduledAt,\n });\n\n if (updated) {\n publishedItems.push(updated);\n if (this.hooks) {\n await this.hooks.doAction(\"cms.content_published\", updated);\n await this.hooks.doAction(`cms.${collection}_published`, updated);\n }\n }\n }\n }\n\n return publishedItems;\n }\n}\n","/**\n * @azlib/cms - Content Revision History & Rollback Manager\n */\n\nimport type {\n ContentItem,\n RevisionDiff,\n RevisionDiffField,\n RevisionRecord,\n} from \"../core/types.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { HooksManager } from \"../core/hooks.js\";\n\nexport class RevisionManager {\n constructor(\n private storage: CMSStorageAdapter,\n private hooks?: HooksManager,\n ) {}\n\n /**\n * Save a revision snapshot for a content item.\n */\n async createRevision(\n item: ContentItem,\n authorId?: string | null,\n note?: string,\n ): Promise<RevisionRecord> {\n const revision = await this.storage.createRevision(\n item.id,\n item.collection,\n item.version,\n item,\n authorId,\n note,\n );\n\n if (this.hooks) {\n await this.hooks.doAction(\"cms.revision_created\", revision);\n }\n\n return revision;\n }\n\n /**\n * Get all revisions for a content item.\n */\n async getRevisions(contentId: string): Promise<RevisionRecord[]> {\n return this.storage.getRevisions(contentId);\n }\n\n /**\n * Get a specific revision by ID.\n */\n async getRevision(revisionId: string): Promise<RevisionRecord | null> {\n return this.storage.getRevision(revisionId);\n }\n\n /**\n * Compute differences between two content snapshots.\n */\n computeDiff(\n oldSnapshot: ContentItem,\n newSnapshot: ContentItem,\n ): RevisionDiff {\n const changes: RevisionDiffField[] = [];\n\n // Check title\n if (oldSnapshot.title !== newSnapshot.title) {\n changes.push({\n field: \"title\",\n oldValue: oldSnapshot.title,\n newValue: newSnapshot.title,\n });\n }\n\n // Check slug\n if (oldSnapshot.slug !== newSnapshot.slug) {\n changes.push({\n field: \"slug\",\n oldValue: oldSnapshot.slug,\n newValue: newSnapshot.slug,\n });\n }\n\n // Check status\n if (oldSnapshot.status !== newSnapshot.status) {\n changes.push({\n field: \"status\",\n oldValue: oldSnapshot.status,\n newValue: newSnapshot.status,\n });\n }\n\n // Check custom data fields (excluding already checked top-level fields)\n const allKeys = new Set([\n ...Object.keys(oldSnapshot.data || {}),\n ...Object.keys(newSnapshot.data || {}),\n ]);\n\n const topLevelFields = new Set([\"title\", \"slug\", \"status\"]);\n\n for (const key of allKeys) {\n if (topLevelFields.has(key)) continue;\n\n const oldVal = oldSnapshot.data?.[key];\n const newVal = newSnapshot.data?.[key];\n if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {\n changes.push({\n field: `data.${key}`,\n oldValue: oldVal,\n newValue: newVal,\n });\n }\n }\n\n return {\n contentId: newSnapshot.id,\n fromVersion: oldSnapshot.version,\n toVersion: newSnapshot.version,\n changes,\n };\n }\n\n /**\n * Restore a content item to a previous revision snapshot.\n */\n async restoreRevision(\n collection: string,\n revisionId: string,\n authorId?: string,\n ): Promise<ContentItem | null> {\n const revision = await this.storage.getRevision(revisionId);\n if (!revision || revision.collection !== collection) {\n return null;\n }\n\n const snapshot = revision.snapshot;\n\n const restored = await this.storage.updateContent(\n collection,\n revision.contentId,\n {\n title: snapshot.title,\n slug: snapshot.slug,\n status: snapshot.status,\n parentId: snapshot.parentId,\n data: snapshot.data,\n authorId: authorId ?? snapshot.authorId,\n },\n );\n\n if (restored) {\n // Create a new revision noting the restoration\n await this.createRevision(\n restored,\n authorId,\n `Restored from revision v${revision.version}`,\n );\n\n if (this.hooks) {\n await this.hooks.doAction(\"cms.revision_restored\", restored, revision);\n }\n }\n\n return restored;\n }\n}\n","/**\n * @azlib/cms - Slug generation and normalization utility\n */\n\n/**\n * Generate a clean, URL-safe slug from any input string.\n */\nexport function slugify(input: string): string {\n if (!input) return \"\";\n\n return input\n .toString()\n .normalize(\"NFKD\") // Normalize unicode accents\n .replace(/[\\u0300-\\u036f]/g, \"\") // Remove accent marks\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9\\s-_]/g, \"\") // Remove invalid characters\n .replace(/[\\s_-]+/g, \"-\") // Replace spaces, underscores, and multiple hyphens with single hyphen\n .replace(/^-+|-+$/g, \"\"); // Trim leading and trailing hyphens\n}\n\n/**\n * Create a unique slug given an existing set of slugs or a check function.\n */\nexport async function resolveUniqueSlug(\n baseSlug: string,\n isSlugTaken: (slug: string) => Promise<boolean> | boolean,\n currentId?: string,\n): Promise<string> {\n const root = slugify(baseSlug) || \"item\";\n let candidate = root;\n let counter = 1;\n\n while (await isSlugTaken(candidate)) {\n counter += 1;\n candidate = `${root}-${counter}`;\n }\n\n return candidate;\n}\n","/**\n * @azlib/cms - Taxonomy & Category/Tag Management\n */\n\nimport type { TaxonomyConfig, TermItem, TermTreeItem } from \"../core/types.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { HooksManager } from \"../core/hooks.js\";\nimport { resolveUniqueSlug, slugify } from \"../content/slug.js\";\n\nexport class TaxonomyManager {\n private registeredTaxonomies = new Map<string, TaxonomyConfig>();\n\n constructor(\n private storage: CMSStorageAdapter,\n private hooks?: HooksManager,\n ) {\n // Register default WordPress-like taxonomies\n this.registerTaxonomy({\n slug: \"categories\",\n label: \"Categories\",\n singularLabel: \"Category\",\n hierarchical: true,\n postTypes: [\"posts\"],\n });\n\n this.registerTaxonomy({\n slug: \"tags\",\n label: \"Tags\",\n singularLabel: \"Tag\",\n hierarchical: false,\n postTypes: [\"posts\"],\n });\n }\n\n /**\n * Register a taxonomy definition.\n */\n registerTaxonomy(config: TaxonomyConfig): void {\n this.registeredTaxonomies.set(config.slug, config);\n }\n\n /**\n * Get all registered taxonomies.\n */\n getTaxonomies(): TaxonomyConfig[] {\n return Array.from(this.registeredTaxonomies.values());\n }\n\n /**\n * Get a single taxonomy configuration by slug.\n */\n getTaxonomy(slug: string): TaxonomyConfig | undefined {\n return this.registeredTaxonomies.get(slug);\n }\n\n /**\n * Create a new term (e.g. category or tag).\n */\n async createTerm(\n taxonomy: string,\n data: {\n name: string;\n slug?: string;\n description?: string;\n parentId?: string | null;\n meta?: Record<string, unknown>;\n },\n ): Promise<TermItem> {\n const taxConfig = this.getTaxonomy(taxonomy);\n if (!taxConfig) {\n throw new Error(\n `[TaxonomyManager] Taxonomy '${taxonomy}' is not registered.`,\n );\n }\n\n const baseSlug = data.slug ? slugify(data.slug) : slugify(data.name);\n const finalSlug = await resolveUniqueSlug(baseSlug, async (s) => {\n const existing = await this.storage.getTermBySlug(taxonomy, s);\n return existing !== null;\n });\n\n const term = await this.storage.createTerm({\n taxonomy,\n name: data.name.trim(),\n slug: finalSlug,\n description: data.description,\n parentId: taxConfig.hierarchical ? (data.parentId ?? null) : null,\n meta: data.meta,\n });\n\n if (this.hooks) {\n await this.hooks.doAction(\"cms.term_created\", term);\n await this.hooks.doAction(`cms.${taxonomy}_term_created`, term);\n }\n\n return term;\n }\n\n /**\n * Get a term by ID.\n */\n async getTermById(id: string): Promise<TermItem | null> {\n return this.storage.getTermById(id);\n }\n\n /**\n * Get a term by slug within a taxonomy.\n */\n async getTermBySlug(\n taxonomy: string,\n slug: string,\n ): Promise<TermItem | null> {\n return this.storage.getTermBySlug(taxonomy, slug);\n }\n\n /**\n * Get terms for a taxonomy.\n */\n async getTerms(\n taxonomy: string,\n options?: { parentId?: string | null },\n ): Promise<TermItem[]> {\n return this.storage.getTerms(taxonomy, options);\n }\n\n /**\n * Build a hierarchical tree of terms for a taxonomy (parent -> children).\n */\n async getTermTree(taxonomy: string): Promise<TermTreeItem[]> {\n const allTerms = await this.storage.getTerms(taxonomy);\n const map = new Map<string, TermTreeItem>();\n const roots: TermTreeItem[] = [];\n\n // Initialize items with children arrays\n for (const term of allTerms) {\n map.set(term.id, { ...term, children: [] });\n }\n\n // Link parents and children\n for (const term of allTerms) {\n const node = map.get(term.id)!;\n if (term.parentId && map.has(term.parentId)) {\n map.get(term.parentId)!.children.push(node);\n } else {\n roots.push(node);\n }\n }\n\n return roots;\n }\n\n /**\n * Update a term.\n */\n async updateTerm(\n id: string,\n updates: {\n name?: string;\n slug?: string;\n description?: string;\n parentId?: string | null;\n meta?: Record<string, unknown>;\n },\n ): Promise<TermItem | null> {\n const existing = await this.storage.getTermById(id);\n if (!existing) return null;\n\n let slug = existing.slug;\n if (updates.slug && updates.slug !== existing.slug) {\n slug = await resolveUniqueSlug(\n updates.slug,\n async (s) => {\n const check = await this.storage.getTermBySlug(existing.taxonomy, s);\n return check !== null && check.id !== id;\n },\n id,\n );\n }\n\n const updated = await this.storage.updateTerm(id, {\n ...updates,\n slug,\n name: updates.name ? updates.name.trim() : existing.name,\n });\n\n if (updated && this.hooks) {\n await this.hooks.doAction(\"cms.term_updated\", updated);\n }\n\n return updated;\n }\n\n /**\n * Delete a term.\n */\n async deleteTerm(id: string): Promise<boolean> {\n const term = await this.storage.getTermById(id);\n if (!term) return false;\n\n const deleted = await this.storage.deleteTerm(id);\n if (deleted && this.hooks) {\n await this.hooks.doAction(\"cms.term_deleted\", term);\n }\n return deleted;\n }\n\n /**\n * Assign term IDs to a content item.\n */\n async assignTerms(contentId: string, termIds: string[]): Promise<void> {\n await this.storage.assignTermsToContent(contentId, termIds);\n if (this.hooks) {\n await this.hooks.doAction(\"cms.terms_assigned\", contentId, termIds);\n }\n }\n\n /**\n * Get all terms assigned to a content item.\n */\n async getContentTerms(\n contentId: string,\n taxonomy?: string,\n ): Promise<TermItem[]> {\n return this.storage.getContentTerms(contentId, taxonomy);\n }\n\n /**\n * Remove terms from a content item.\n */\n async removeTerms(contentId: string, termIds: string[]): Promise<void> {\n await this.storage.removeTermsFromContent(contentId, termIds);\n }\n}\n","/**\n * @azlib/cms - Media & Asset Management\n */\n\nimport type { MediaItem, PaginatedResult } from \"../core/types.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { HooksManager } from \"../core/hooks.js\";\nimport { slugify } from \"../content/slug.js\";\n\nexport interface MediaUploadInput {\n filename: string;\n mimeType: string;\n sizeBytes: number;\n url?: string;\n width?: number;\n height?: number;\n altText?: string;\n caption?: string;\n variants?: Record<string, string>;\n}\n\nexport class MediaManager {\n private allowedMimePrefixes = [\n \"image/\",\n \"video/\",\n \"audio/\",\n \"application/pdf\",\n \"text/\",\n ];\n\n constructor(\n private storage: CMSStorageAdapter,\n private hooks?: HooksManager,\n private publicBaseUrl = \"/uploads\",\n ) {}\n\n /**\n * Upload / register a new media item.\n */\n async upload(\n input: MediaUploadInput,\n authorId?: string | null,\n ): Promise<MediaItem> {\n // Validate MIME type\n const isAllowed = this.allowedMimePrefixes.some((prefix) =>\n input.mimeType.startsWith(prefix),\n );\n if (!isAllowed) {\n throw new Error(\n `[MediaManager] Unsupported MIME type: ${input.mimeType}`,\n );\n }\n\n // Clean filename\n const extMatch = input.filename.match(/\\.([a-zA-Z0-9]+)$/);\n const ext = extMatch ? `.${extMatch[1].toLowerCase()}` : \"\";\n const nameWithoutExt = input.filename.replace(/\\.[^/.]+$/, \"\");\n const cleanFilename = `${slugify(nameWithoutExt)}${ext}`;\n\n const url = input.url ?? `${this.publicBaseUrl}/${cleanFilename}`;\n\n const media = await this.storage.createMedia({\n filename: cleanFilename,\n originalName: input.filename,\n mimeType: input.mimeType,\n sizeBytes: input.sizeBytes,\n url,\n width: input.width,\n height: input.height,\n altText: input.altText,\n caption: input.caption,\n variants: input.variants,\n authorId,\n });\n\n if (this.hooks) {\n await this.hooks.doAction(\"cms.media_uploaded\", media);\n }\n\n return media;\n }\n\n /**\n * Get a media item by ID.\n */\n async get(id: string): Promise<MediaItem | null> {\n return this.storage.getMedia(id);\n }\n\n /**\n * Find media items.\n */\n async find(options?: {\n search?: string;\n mimeType?: string;\n authorId?: string;\n limit?: number;\n offset?: number;\n }): Promise<PaginatedResult<MediaItem>> {\n return this.storage.findMedia(options);\n }\n\n /**\n * Update media metadata (alt text, caption, dimensions).\n */\n async updateMetadata(\n id: string,\n updates: {\n altText?: string;\n caption?: string;\n width?: number;\n height?: number;\n },\n ): Promise<MediaItem | null> {\n const updated = await this.storage.updateMedia(id, updates);\n if (updated && this.hooks) {\n await this.hooks.doAction(\"cms.media_updated\", updated);\n }\n return updated;\n }\n\n /**\n * Delete a media item.\n */\n async delete(id: string): Promise<boolean> {\n const media = await this.storage.getMedia(id);\n if (!media) return false;\n\n const deleted = await this.storage.deleteMedia(id);\n if (deleted && this.hooks) {\n await this.hooks.doAction(\"cms.media_deleted\", media);\n }\n return deleted;\n }\n}\n","/**\n * @azlib/cms - Role-Based Access Control (RBAC) & Capabilities\n */\n\nimport type {\n CMSCapability,\n CMSUser,\n ContentItem,\n UserRole,\n} from \"../core/types.js\";\n\nexport const DEFAULT_ROLE_CAPABILITIES: Record<string, string[]> = {\n admin: [\n \"manage_options\",\n \"manage_taxonomies\",\n \"upload_files\",\n \"delete_files\",\n \"edit_posts\",\n \"edit_others_posts\",\n \"publish_posts\",\n \"delete_posts\",\n \"delete_others_posts\",\n \"read_private_posts\",\n ],\n editor: [\n \"manage_taxonomies\",\n \"upload_files\",\n \"delete_files\",\n \"edit_posts\",\n \"edit_others_posts\",\n \"publish_posts\",\n \"delete_posts\",\n \"delete_others_posts\",\n \"read_private_posts\",\n ],\n author: [\"upload_files\", \"edit_posts\", \"publish_posts\", \"delete_posts\"],\n contributor: [\"edit_posts\", \"delete_posts\"],\n subscriber: [\"read\"],\n};\n\nexport class RBACManager {\n private roleCapabilities = new Map<string, Set<string>>();\n\n constructor() {\n for (const [role, caps] of Object.entries(DEFAULT_ROLE_CAPABILITIES)) {\n this.roleCapabilities.set(role, new Set(caps));\n }\n }\n\n /**\n * Register a custom role with its capabilities.\n */\n registerRole(role: string, capabilities: string[]): void {\n this.roleCapabilities.set(role, new Set(capabilities));\n }\n\n /**\n * Add a capability to an existing role.\n */\n addCapabilityToRole(role: string, capability: string): void {\n let caps = this.roleCapabilities.get(role);\n if (!caps) {\n caps = new Set();\n this.roleCapabilities.set(role, caps);\n }\n caps.add(capability);\n }\n\n /**\n * Get all capabilities assigned to a role.\n */\n getRoleCapabilities(role: string): string[] {\n const caps = this.roleCapabilities.get(role);\n return caps ? Array.from(caps) : [];\n }\n\n /**\n * Check if a user possesses a specific capability.\n * If a target content item context is provided, checks object ownership rules.\n */\n can(\n user: CMSUser | null | undefined,\n capability: CMSCapability,\n context?: { contentItem?: ContentItem },\n ): boolean {\n if (!user || user.active === false) return false;\n\n // Check user-specific capability overrides\n if (user.capabilities && user.capabilities.includes(capability)) {\n return true;\n }\n\n const roleCaps = this.roleCapabilities.get(user.role);\n if (!roleCaps) return false;\n\n // Admin has full access\n if (user.role === \"admin\") return true;\n\n // Handle content item contextual checks (own vs others)\n if (context?.contentItem) {\n const isOwner = context.contentItem.authorId === user.id;\n\n if (capability === \"edit_posts\") {\n if (isOwner) {\n return roleCaps.has(\"edit_posts\");\n }\n return roleCaps.has(\"edit_others_posts\");\n }\n\n if (capability === \"delete_posts\") {\n if (isOwner) {\n return roleCaps.has(\"delete_posts\");\n }\n return roleCaps.has(\"delete_others_posts\");\n }\n }\n\n return roleCaps.has(capability);\n }\n}\n","/**\n * @azlib/cms - In-Memory Storage Adapter\n */\n\nimport type {\n ContentItem,\n ContentQueryOptions,\n MediaItem,\n OptionItem,\n PaginatedResult,\n RevisionRecord,\n TermItem,\n} from \"../core/types.js\";\nimport type { CMSStorageAdapter } from \"./storage-contract.js\";\n\nfunction generateId(prefix = \"\"): string {\n return `${prefix}${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 9)}`;\n}\n\nexport class MemoryStorageAdapter implements CMSStorageAdapter {\n private content = new Map<string, ContentItem>();\n private revisions = new Map<string, RevisionRecord>();\n private terms = new Map<string, TermItem>();\n private contentTerms = new Map<string, Set<string>>(); // contentId -> Set of termIds\n private media = new Map<string, MediaItem>();\n private options = new Map<string, OptionItem>();\n\n async init(): Promise<void> {}\n async close(): Promise<void> {}\n\n async createContent<T extends Record<string, unknown>>(\n item: Omit<ContentItem<T>, \"id\" | \"createdAt\" | \"updatedAt\" | \"version\">,\n ): Promise<ContentItem<T>> {\n const id = generateId(\"cnt_\");\n const now = new Date().toISOString();\n const fullItem: ContentItem<T> = {\n ...item,\n id,\n version: 1,\n createdAt: now,\n updatedAt: now,\n };\n this.content.set(id, fullItem as ContentItem);\n return JSON.parse(JSON.stringify(fullItem));\n }\n\n async getContent<T extends Record<string, unknown>>(\n collection: string,\n id: string,\n ): Promise<ContentItem<T> | null> {\n const item = this.content.get(id);\n if (!item || item.collection !== collection) return null;\n return JSON.parse(JSON.stringify(item)) as ContentItem<T>;\n }\n\n async getContentBySlug<T extends Record<string, unknown>>(\n collection: string,\n slug: string,\n ): Promise<ContentItem<T> | null> {\n for (const item of this.content.values()) {\n if (item.collection === collection && item.slug === slug) {\n return JSON.parse(JSON.stringify(item)) as ContentItem<T>;\n }\n }\n return null;\n }\n\n async findContent<T extends Record<string, unknown>>(\n collection: string,\n options: ContentQueryOptions = {},\n ): Promise<PaginatedResult<ContentItem<T>>> {\n let list: ContentItem[] = [];\n\n for (const item of this.content.values()) {\n if (item.collection !== collection) continue;\n\n // Status filter\n if (options.status) {\n const statuses = Array.isArray(options.status)\n ? options.status\n : [options.status];\n if (!statuses.includes(item.status)) continue;\n }\n\n // Author filter\n if (options.authorId && item.authorId !== options.authorId) continue;\n\n // Parent filter\n if (options.parentId !== undefined && item.parentId !== options.parentId)\n continue;\n\n // Term IDs filter\n if (options.termIds && options.termIds.length > 0) {\n const assigned = this.contentTerms.get(item.id);\n if (!assigned || !options.termIds.some((tId) => assigned.has(tId))) {\n continue;\n }\n }\n\n // Search\n if (options.search) {\n const query = options.search.toLowerCase();\n const inTitle = item.title?.toLowerCase().includes(query);\n const inSlug = item.slug.toLowerCase().includes(query);\n const inData = JSON.stringify(item.data).toLowerCase().includes(query);\n if (!inTitle && !inSlug && !inData) continue;\n }\n\n // Where matches\n if (options.where) {\n let match = true;\n for (const [key, val] of Object.entries(options.where)) {\n if (\n item.data[key] !== val &&\n (item as unknown as Record<string, unknown>)[key] !== val\n ) {\n match = false;\n break;\n }\n }\n if (!match) continue;\n }\n\n list.push(item);\n }\n\n const total = list.length;\n\n // Sorting\n const orderBy = options.orderBy || \"createdAt\";\n const dir = options.orderDirection === \"asc\" ? 1 : -1;\n\n list.sort((a, b) => {\n const valA =\n (a as unknown as Record<string, unknown>)[orderBy] ??\n a.data[orderBy] ??\n \"\";\n const valB =\n (b as unknown as Record<string, unknown>)[orderBy] ??\n b.data[orderBy] ??\n \"\";\n if (valA < valB) return -1 * dir;\n if (valA > valB) return 1 * dir;\n return 0;\n });\n\n // Pagination\n const offset = options.offset ?? 0;\n const limit = options.limit ?? 20;\n const paged = list.slice(offset, offset + limit);\n\n return {\n items: JSON.parse(JSON.stringify(paged)) as ContentItem<T>[],\n total,\n limit,\n offset,\n hasMore: offset + limit < total,\n };\n }\n\n async updateContent<T extends Record<string, unknown>>(\n collection: string,\n id: string,\n updates: Partial<Omit<ContentItem<T>, \"id\" | \"collection\" | \"createdAt\">>,\n ): Promise<ContentItem<T> | null> {\n const existing = this.content.get(id);\n if (!existing || existing.collection !== collection) return null;\n\n const updated: ContentItem = {\n ...existing,\n ...updates,\n data: {\n ...existing.data,\n ...(updates.data || {}),\n },\n version: existing.version + 1,\n updatedAt: new Date().toISOString(),\n };\n\n this.content.set(id, updated);\n return JSON.parse(JSON.stringify(updated)) as ContentItem<T>;\n }\n\n async deleteContent(collection: string, id: string): Promise<boolean> {\n const existing = this.content.get(id);\n if (!existing || existing.collection !== collection) return false;\n\n this.content.delete(id);\n this.contentTerms.delete(id);\n await this.deleteRevisionsByContentId(id);\n return true;\n }\n\n async countContent(\n collection: string,\n options: ContentQueryOptions = {},\n ): Promise<number> {\n const res = await this.findContent(collection, {\n ...options,\n limit: 1_000_000,\n });\n return res.total;\n }\n\n // Revisions\n async createRevision(\n contentId: string,\n collection: string,\n version: number,\n snapshot: ContentItem,\n authorId?: string | null,\n note?: string,\n ): Promise<RevisionRecord> {\n const id = generateId(\"rev_\");\n const record: RevisionRecord = {\n id,\n contentId,\n collection,\n version,\n snapshot: JSON.parse(JSON.stringify(snapshot)),\n authorId,\n note,\n createdAt: new Date().toISOString(),\n };\n this.revisions.set(id, record);\n return JSON.parse(JSON.stringify(record));\n }\n\n async getRevisions(contentId: string): Promise<RevisionRecord[]> {\n const list: RevisionRecord[] = [];\n for (const rev of this.revisions.values()) {\n if (rev.contentId === contentId) {\n list.push(rev);\n }\n }\n list.sort((a, b) => b.version - a.version);\n return JSON.parse(JSON.stringify(list));\n }\n\n async getRevision(revisionId: string): Promise<RevisionRecord | null> {\n const rev = this.revisions.get(revisionId);\n return rev ? JSON.parse(JSON.stringify(rev)) : null;\n }\n\n async deleteRevisionsByContentId(contentId: string): Promise<number> {\n let count = 0;\n for (const [id, rev] of this.revisions.entries()) {\n if (rev.contentId === contentId) {\n this.revisions.delete(id);\n count++;\n }\n }\n return count;\n }\n\n // Taxonomies & Terms\n async createTerm(\n term: Omit<TermItem, \"id\" | \"count\" | \"createdAt\" | \"updatedAt\">,\n ): Promise<TermItem> {\n const id = generateId(\"trm_\");\n const now = new Date().toISOString();\n const item: TermItem = {\n ...term,\n id,\n count: 0,\n createdAt: now,\n updatedAt: now,\n };\n this.terms.set(id, item);\n return JSON.parse(JSON.stringify(item));\n }\n\n async getTermById(id: string): Promise<TermItem | null> {\n const term = this.terms.get(id);\n return term ? JSON.parse(JSON.stringify(term)) : null;\n }\n\n async getTermBySlug(\n taxonomy: string,\n slug: string,\n ): Promise<TermItem | null> {\n for (const term of this.terms.values()) {\n if (term.taxonomy === taxonomy && term.slug === slug) {\n return JSON.parse(JSON.stringify(term));\n }\n }\n return null;\n }\n\n async getTerms(\n taxonomy: string,\n options?: { parentId?: string | null },\n ): Promise<TermItem[]> {\n const list: TermItem[] = [];\n for (const term of this.terms.values()) {\n if (term.taxonomy !== taxonomy) continue;\n if (options?.parentId !== undefined && term.parentId !== options.parentId)\n continue;\n list.push(term);\n }\n return JSON.parse(JSON.stringify(list));\n }\n\n async updateTerm(\n id: string,\n updates: Partial<Omit<TermItem, \"id\" | \"taxonomy\" | \"createdAt\">>,\n ): Promise<TermItem | null> {\n const term = this.terms.get(id);\n if (!term) return null;\n const updated: TermItem = {\n ...term,\n ...updates,\n updatedAt: new Date().toISOString(),\n };\n this.terms.set(id, updated);\n return JSON.parse(JSON.stringify(updated));\n }\n\n async deleteTerm(id: string): Promise<boolean> {\n const exists = this.terms.delete(id);\n if (exists) {\n for (const set of this.contentTerms.values()) {\n set.delete(id);\n }\n }\n return exists;\n }\n\n async assignTermsToContent(\n contentId: string,\n termIds: string[],\n ): Promise<void> {\n let set = this.contentTerms.get(contentId);\n if (!set) {\n set = new Set();\n this.contentTerms.set(contentId, set);\n }\n for (const id of termIds) {\n set.add(id);\n }\n this.recalculateTermCounts();\n }\n\n async getContentTerms(\n contentId: string,\n taxonomy?: string,\n ): Promise<TermItem[]> {\n const set = this.contentTerms.get(contentId);\n if (!set) return [];\n const list: TermItem[] = [];\n for (const termId of set) {\n const term = this.terms.get(termId);\n if (term) {\n if (!taxonomy || term.taxonomy === taxonomy) {\n list.push(term);\n }\n }\n }\n return JSON.parse(JSON.stringify(list));\n }\n\n async removeTermsFromContent(\n contentId: string,\n termIds: string[],\n ): Promise<void> {\n const set = this.contentTerms.get(contentId);\n if (!set) return;\n for (const id of termIds) {\n set.delete(id);\n }\n this.recalculateTermCounts();\n }\n\n private recalculateTermCounts(): void {\n const counts = new Map<string, number>();\n for (const set of this.contentTerms.values()) {\n for (const termId of set) {\n counts.set(termId, (counts.get(termId) || 0) + 1);\n }\n }\n for (const [id, term] of this.terms.entries()) {\n term.count = counts.get(id) || 0;\n }\n }\n\n // Media\n async createMedia(\n item: Omit<MediaItem, \"id\" | \"createdAt\" | \"updatedAt\">,\n ): Promise<MediaItem> {\n const id = generateId(\"med_\");\n const now = new Date().toISOString();\n const mediaItem: MediaItem = {\n ...item,\n id,\n createdAt: now,\n updatedAt: now,\n };\n this.media.set(id, mediaItem);\n return JSON.parse(JSON.stringify(mediaItem));\n }\n\n async getMedia(id: string): Promise<MediaItem | null> {\n const m = this.media.get(id);\n return m ? JSON.parse(JSON.stringify(m)) : null;\n }\n\n async findMedia(\n options: {\n search?: string;\n mimeType?: string;\n authorId?: string;\n limit?: number;\n offset?: number;\n } = {},\n ): Promise<PaginatedResult<MediaItem>> {\n const list: MediaItem[] = [];\n for (const item of this.media.values()) {\n if (options.mimeType && !item.mimeType.startsWith(options.mimeType))\n continue;\n if (options.authorId && item.authorId !== options.authorId) continue;\n if (options.search) {\n const q = options.search.toLowerCase();\n if (\n !item.filename.toLowerCase().includes(q) &&\n !item.originalName.toLowerCase().includes(q) &&\n !item.altText?.toLowerCase().includes(q)\n ) {\n continue;\n }\n }\n list.push(item);\n }\n\n list.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n const total = list.length;\n const offset = options.offset ?? 0;\n const limit = options.limit ?? 20;\n\n return {\n items: JSON.parse(JSON.stringify(list.slice(offset, offset + limit))),\n total,\n limit,\n offset,\n hasMore: offset + limit < total,\n };\n }\n\n async updateMedia(\n id: string,\n updates: Partial<Omit<MediaItem, \"id\" | \"createdAt\">>,\n ): Promise<MediaItem | null> {\n const m = this.media.get(id);\n if (!m) return null;\n const updated: MediaItem = {\n ...m,\n ...updates,\n updatedAt: new Date().toISOString(),\n };\n this.media.set(id, updated);\n return JSON.parse(JSON.stringify(updated));\n }\n\n async deleteMedia(id: string): Promise<boolean> {\n return this.media.delete(id);\n }\n\n // Options\n async getOption<T = unknown>(key: string): Promise<OptionItem<T> | null> {\n const opt = this.options.get(key);\n return opt ? (JSON.parse(JSON.stringify(opt)) as OptionItem<T>) : null;\n }\n\n async setOption<T = unknown>(item: OptionItem<T>): Promise<void> {\n this.options.set(item.key, JSON.parse(JSON.stringify(item)));\n }\n\n async deleteOption(key: string): Promise<boolean> {\n return this.options.delete(key);\n }\n\n async getOptions(namespace?: string): Promise<OptionItem[]> {\n const list: OptionItem[] = [];\n for (const opt of this.options.values()) {\n if (namespace && opt.namespace !== namespace) continue;\n list.push(opt);\n }\n return JSON.parse(JSON.stringify(list));\n }\n}\n","/**\n * @azlib/cms - Master CMS Engine Orchestrator\n */\n\nimport type {\n CMSConfig,\n CollectionConfig,\n ContentItem,\n ContentQueryOptions,\n FieldDefinition,\n PaginatedResult,\n RevisionDiff,\n RevisionRecord,\n TaxonomyConfig,\n} from \"./types.js\";\nimport type {\n CMSPlugin,\n CMSPluginContext,\n CustomRouteHandler,\n} from \"./plugin.js\";\nimport { normalizeConfig } from \"./config.js\";\nimport { HooksManager } from \"./hooks.js\";\nimport { OptionsManager } from \"./options.js\";\nimport { ContentLifecycle } from \"../content/lifecycle.js\";\nimport { RevisionManager } from \"../content/revisions.js\";\nimport { validateAndNormalizeData } from \"../content/schema.js\";\nimport { resolveUniqueSlug, slugify } from \"../content/slug.js\";\nimport { TaxonomyManager } from \"../taxonomy/taxonomy.js\";\nimport { MediaManager } from \"../media/media-manager.js\";\nimport { RBACManager } from \"../auth/rbac.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport { MemoryStorageAdapter } from \"../storage/memory-adapter.js\";\n\nexport interface CreateContentInput {\n title?: string;\n slug?: string;\n status?: ContentItem[\"status\"];\n parentId?: string | null;\n scheduledAt?: string | null;\n data?: Record<string, unknown>;\n terms?: Record<string, string[]>;\n}\n\nexport interface UpdateContentInput {\n title?: string;\n slug?: string;\n status?: ContentItem[\"status\"];\n parentId?: string | null;\n scheduledAt?: string | null;\n data?: Record<string, unknown>;\n terms?: Record<string, string[]>;\n}\n\nexport interface CollectionService<\n TData extends Record<string, unknown> = Record<string, unknown>,\n> {\n readonly config: CollectionConfig;\n create(\n input: CreateContentInput,\n authorId?: string | null,\n ): Promise<ContentItem<TData>>;\n findById(id: string): Promise<ContentItem<TData> | null>;\n findBySlug(slug: string): Promise<ContentItem<TData> | null>;\n find(\n options?: ContentQueryOptions,\n ): Promise<PaginatedResult<ContentItem<TData>>>;\n update(\n id: string,\n input: UpdateContentInput,\n authorId?: string | null,\n revisionNote?: string,\n ): Promise<ContentItem<TData> | null>;\n delete(id: string): Promise<boolean>;\n publish(\n id: string,\n authorId?: string | null,\n ): Promise<ContentItem<TData> | null>;\n schedule(\n id: string,\n scheduledAt: Date | string,\n authorId?: string | null,\n ): Promise<ContentItem<TData> | null>;\n getRevisions(id: string): Promise<RevisionRecord[]>;\n getRevision(revisionId: string): Promise<RevisionRecord | null>;\n restoreRevision(\n id: string,\n revisionId: string,\n authorId?: string,\n ): Promise<ContentItem<TData> | null>;\n getDiff(\n oldVersion: ContentItem<TData>,\n newVersion: ContentItem<TData>,\n ): RevisionDiff;\n}\n\nexport class CMSEngine {\n readonly config: CMSConfig;\n readonly hooks: HooksManager;\n readonly storage: CMSStorageAdapter;\n readonly options: OptionsManager;\n readonly taxonomies: TaxonomyManager;\n readonly media: MediaManager;\n readonly rbac: RBACManager;\n readonly revisions: RevisionManager;\n readonly lifecycle: ContentLifecycle;\n\n private collections = new Map<string, CollectionConfig>();\n private plugins = new Map<string, CMSPlugin>();\n private customRoutes = new Map<string, Map<string, CustomRouteHandler>>();\n private pendingPluginSetups: (Promise<void> | void)[] = [];\n\n constructor(\n config: Partial<CMSConfig> = {},\n storage?: CMSStorageAdapter,\n hooks?: HooksManager,\n ) {\n this.config = normalizeConfig(config);\n this.hooks = hooks ?? new HooksManager();\n this.storage = storage ?? new MemoryStorageAdapter();\n\n this.options = new OptionsManager(this.storage, this.hooks);\n this.taxonomies = new TaxonomyManager(this.storage, this.hooks);\n this.media = new MediaManager(this.storage, this.hooks);\n this.rbac = new RBACManager();\n this.revisions = new RevisionManager(this.storage, this.hooks);\n this.lifecycle = new ContentLifecycle(this.storage, this.hooks);\n\n // Register collections from config\n for (const coll of this.config.collections) {\n this.collections.set(coll.slug, coll);\n }\n\n // Register taxonomies from config\n if (this.config.taxonomies) {\n for (const tax of this.config.taxonomies) {\n this.taxonomies.registerTaxonomy(tax);\n }\n }\n\n // Register plugins from config\n if (this.config.plugins) {\n for (const plugin of this.config.plugins) {\n this.use(plugin);\n }\n }\n }\n\n /**\n * Register a plugin with the CMS engine.\n */\n use(plugin: CMSPlugin): this {\n if (this.plugins.has(plugin.name)) {\n throw new Error(\n `[CMSEngine] Plugin '${plugin.name}' is already registered.`,\n );\n }\n this.plugins.set(plugin.name, plugin);\n\n // Register declarative collections\n if (plugin.collections) {\n for (const coll of plugin.collections) {\n this.registerCollection(coll);\n }\n }\n\n // Register declarative taxonomies\n if (plugin.taxonomies) {\n for (const tax of plugin.taxonomies) {\n this.taxonomies.registerTaxonomy(tax);\n }\n }\n\n // Extend existing collection fields\n if (plugin.extendCollections) {\n for (const [slug, fields] of Object.entries(plugin.extendCollections)) {\n this.extendCollection(slug, fields);\n }\n }\n\n // Run plugin setup callback\n if (plugin.setup) {\n const context: CMSPluginContext = {\n engine: this,\n hooks: this.hooks,\n storage: this.storage,\n options: this.options,\n taxonomies: this.taxonomies,\n media: this.media,\n rbac: this.rbac,\n revisions: this.revisions,\n lifecycle: this.lifecycle,\n registerCollection: (c) => this.registerCollection(c),\n extendCollection: (s, f) => this.extendCollection(s, f),\n registerTaxonomy: (t) => this.taxonomies.registerTaxonomy(t),\n registerRoute: (m, p, h) => this.registerRoute(m, p, h),\n };\n\n const setupResult = plugin.setup(context);\n if (setupResult instanceof Promise) {\n this.pendingPluginSetups.push(setupResult);\n }\n }\n\n return this;\n }\n\n /**\n * Get all registered plugins.\n */\n getPlugins(): readonly CMSPlugin[] {\n return Array.from(this.plugins.values());\n }\n\n /**\n * Get a registered plugin by name.\n */\n getPlugin(name: string): CMSPlugin | undefined {\n return this.plugins.get(name);\n }\n\n /**\n * Check if a plugin is registered.\n */\n hasPlugin(name: string): boolean {\n return this.plugins.has(name);\n }\n\n /**\n * Register a collection dynamically.\n */\n registerCollection(coll: CollectionConfig): void {\n this.collections.set(coll.slug, coll);\n }\n\n /**\n * Inject additional field definitions into an existing collection.\n */\n extendCollection(slug: string, newFields: readonly FieldDefinition[]): void {\n const existing = this.collections.get(slug);\n if (!existing) {\n throw new Error(\n `[CMSEngine] Cannot extend non-existent collection '${slug}'.`,\n );\n }\n const existingFieldNames = new Set(existing.fields.map((f) => f.name));\n const addedFields = newFields.filter(\n (f) => !existingFieldNames.has(f.name),\n );\n this.collections.set(slug, {\n ...existing,\n fields: [...existing.fields, ...addedFields],\n });\n }\n\n /**\n * Register a custom Web Standard HTTP route on the engine.\n */\n registerRoute(\n method: string,\n path: string,\n handler: CustomRouteHandler,\n ): void {\n const normalizedMethod = method.toUpperCase();\n let methodMap = this.customRoutes.get(normalizedMethod);\n if (!methodMap) {\n methodMap = new Map();\n this.customRoutes.set(normalizedMethod, methodMap);\n }\n methodMap.set(path, handler);\n }\n\n /**\n * Get all custom routes registered across all HTTP methods.\n */\n getCustomRoutes(): Map<string, Map<string, CustomRouteHandler>> {\n return this.customRoutes;\n }\n\n /**\n * Initialize storage and trigger bootstrap hooks.\n */\n async init(): Promise<void> {\n await this.storage.init();\n\n // Await any pending asynchronous plugin setups\n if (this.pendingPluginSetups.length > 0) {\n await Promise.all(this.pendingPluginSetups);\n this.pendingPluginSetups = [];\n }\n\n // Populate initial site options if not already set\n if (this.config.site) {\n const hasTitle = await this.options.has(\"site_name\");\n if (!hasTitle) {\n await this.options.set(\"site_name\", this.config.site.name);\n }\n }\n\n // Run onInit hooks on registered plugins\n for (const plugin of this.plugins.values()) {\n if (plugin.onInit) {\n await plugin.onInit(this);\n }\n }\n\n await this.hooks.doAction(\"cms.plugins_initialized\", this);\n await this.hooks.doAction(\"cms.init\", this);\n }\n\n /**\n * Close storage connections and run plugin teardown hooks.\n */\n async close(): Promise<void> {\n for (const plugin of this.plugins.values()) {\n if (plugin.onClose) {\n await plugin.onClose(this);\n }\n }\n await this.storage.close();\n await this.hooks.doAction(\"cms.close\", this);\n }\n\n /**\n * Get all registered collection configurations.\n */\n getCollections(): CollectionConfig[] {\n return Array.from(this.collections.values());\n }\n\n /**\n * Get a single collection configuration.\n */\n getCollectionConfig(slug: string): CollectionConfig | undefined {\n return this.collections.get(slug);\n }\n\n /**\n * Access high-level CRUD service for a collection.\n */\n collection<TData extends Record<string, unknown> = Record<string, unknown>>(\n slug: string,\n ): CollectionService<TData> {\n const collConfig = this.collections.get(slug);\n if (!collConfig) {\n throw new Error(`[CMSEngine] Collection '${slug}' is not registered.`);\n }\n\n const self = this;\n\n return {\n config: collConfig,\n\n async create(input, authorId = null) {\n const filteredInput = await self.hooks.applyFilters<CreateContentInput>(\n \"cms.before_create_input\",\n input,\n { collection: slug },\n );\n\n const inputData: Record<string, unknown> = {\n ...(filteredInput.data || {}),\n };\n if (filteredInput.title !== undefined)\n inputData.title = filteredInput.title;\n if (filteredInput.slug !== undefined)\n inputData.slug = filteredInput.slug;\n if (filteredInput.status !== undefined)\n inputData.status = filteredInput.status;\n\n // Validate and normalize custom fields\n const { data: normalizedData, errors } = validateAndNormalizeData(\n collConfig.fields,\n inputData,\n );\n\n if (Object.keys(errors).length > 0) {\n throw new Error(\n `[CMSEngine] Validation failed for collection '${slug}': ${JSON.stringify(errors)}`,\n );\n }\n\n // Generate unique slug\n const title = (filteredInput.title ??\n normalizedData.title ??\n \"\") as string;\n const baseSlug = filteredInput.slug\n ? slugify(filteredInput.slug)\n : slugify(title) || \"item\";\n const finalSlug = await resolveUniqueSlug(baseSlug, async (s) => {\n const existing = await self.storage.getContentBySlug(slug, s);\n return existing !== null;\n });\n\n const status =\n filteredInput.status ??\n (collConfig.draftable ? \"draft\" : \"published\");\n const nowIso = new Date().toISOString();\n\n // Create item\n const item = await self.storage.createContent<TData>({\n collection: slug,\n slug: finalSlug,\n title,\n status,\n parentId: collConfig.hierarchical\n ? (filteredInput.parentId ?? null)\n : null,\n authorId,\n publishedAt: status === \"published\" ? nowIso : null,\n scheduledAt:\n status === \"scheduled\" ? (filteredInput.scheduledAt ?? null) : null,\n data: normalizedData as TData,\n terms: filteredInput.terms,\n });\n\n // Assign terms if provided\n if (filteredInput.terms) {\n const allTermIds = Object.values(filteredInput.terms).flat();\n if (allTermIds.length > 0) {\n await self.taxonomies.assignTerms(item.id, allTermIds);\n }\n }\n\n // Create initial revision\n if (collConfig.revisions) {\n await self.revisions.createRevision(\n item,\n authorId,\n \"Initial creation\",\n );\n }\n\n await self.hooks.doAction(\"cms.content_created\", item);\n await self.hooks.doAction(`cms.${slug}_created`, item);\n\n return self.hooks.applyFilters<ContentItem<TData>>(\n \"cms.after_create_item\",\n item,\n { collection: slug },\n );\n },\n\n async findById(id) {\n return self.storage.getContent<TData>(slug, id);\n },\n\n async findBySlug(contentSlug) {\n return self.storage.getContentBySlug<TData>(slug, contentSlug);\n },\n\n async find(options = {}) {\n const filteredOptions =\n await self.hooks.applyFilters<ContentQueryOptions>(\n \"cms.find_options\",\n options,\n { collection: slug },\n );\n return self.storage.findContent<TData>(slug, filteredOptions);\n },\n\n async update(id, input, authorId = null, revisionNote) {\n const existing = await self.storage.getContent<TData>(slug, id);\n if (!existing) return null;\n\n const filteredInput = await self.hooks.applyFilters<UpdateContentInput>(\n \"cms.before_update_input\",\n input,\n { collection: slug, id, existing },\n );\n\n const mergedData: Record<string, unknown> = {\n ...existing.data,\n ...(filteredInput.data || {}),\n };\n if (filteredInput.title !== undefined)\n mergedData.title = filteredInput.title;\n else if (existing.title !== undefined && mergedData.title === undefined)\n mergedData.title = existing.title;\n if (filteredInput.slug !== undefined)\n mergedData.slug = filteredInput.slug;\n else if (existing.slug !== undefined && mergedData.slug === undefined)\n mergedData.slug = existing.slug;\n if (filteredInput.status !== undefined)\n mergedData.status = filteredInput.status;\n else if (\n existing.status !== undefined &&\n mergedData.status === undefined\n )\n mergedData.status = existing.status;\n\n const { data: normalizedData, errors } = validateAndNormalizeData(\n collConfig.fields,\n mergedData,\n );\n\n if (Object.keys(errors).length > 0) {\n throw new Error(\n `[CMSEngine] Validation failed updating '${slug}': ${JSON.stringify(errors)}`,\n );\n }\n\n let updatedSlug = existing.slug;\n if (filteredInput.slug && filteredInput.slug !== existing.slug) {\n updatedSlug = await resolveUniqueSlug(\n filteredInput.slug,\n async (s) => {\n const check = await self.storage.getContentBySlug(slug, s);\n return check !== null && check.id !== id;\n },\n id,\n );\n }\n\n const nextStatus = filteredInput.status ?? existing.status;\n const nowIso = new Date().toISOString();\n let publishedAt = existing.publishedAt;\n if (nextStatus === \"published\" && !publishedAt) {\n publishedAt = nowIso;\n }\n\n const updated = await self.storage.updateContent<TData>(slug, id, {\n title:\n filteredInput.title !== undefined\n ? filteredInput.title\n : existing.title,\n slug: updatedSlug,\n status: nextStatus,\n parentId: collConfig.hierarchical\n ? filteredInput.parentId !== undefined\n ? filteredInput.parentId\n : existing.parentId\n : null,\n scheduledAt:\n filteredInput.scheduledAt !== undefined\n ? filteredInput.scheduledAt\n : existing.scheduledAt,\n publishedAt,\n authorId: authorId ?? existing.authorId,\n data: normalizedData as TData,\n terms:\n filteredInput.terms !== undefined\n ? filteredInput.terms\n : existing.terms,\n });\n\n if (updated) {\n // Update term associations if terms given\n if (filteredInput.terms) {\n const allTermIds = Object.values(filteredInput.terms).flat();\n await self.taxonomies.assignTerms(updated.id, allTermIds);\n }\n\n // Create revision snapshot\n if (collConfig.revisions) {\n await self.revisions.createRevision(\n updated,\n authorId,\n revisionNote ?? `Updated version ${updated.version}`,\n );\n }\n\n await self.hooks.doAction(\"cms.content_updated\", updated);\n await self.hooks.doAction(`cms.${slug}_updated`, updated);\n\n return self.hooks.applyFilters<ContentItem<TData>>(\n \"cms.after_update_item\",\n updated,\n { collection: slug },\n );\n }\n\n return updated;\n },\n\n async delete(id) {\n const item = await self.storage.getContent(slug, id);\n if (!item) return false;\n\n const deleted = await self.storage.deleteContent(slug, id);\n if (deleted) {\n await self.hooks.doAction(\"cms.content_deleted\", item);\n await self.hooks.doAction(`cms.${slug}_deleted`, item);\n }\n return deleted;\n },\n\n async publish(id, authorId = null) {\n return this.update(\n id,\n { status: \"published\" },\n authorId,\n \"Published content\",\n );\n },\n\n async schedule(id, scheduledAt, authorId = null) {\n const dateStr =\n scheduledAt instanceof Date ? scheduledAt.toISOString() : scheduledAt;\n return this.update(\n id,\n { status: \"scheduled\", scheduledAt: dateStr },\n authorId,\n `Scheduled for publish at ${dateStr}`,\n );\n },\n\n async getRevisions(id) {\n return self.revisions.getRevisions(id);\n },\n\n async getRevision(revisionId) {\n return self.revisions.getRevision(revisionId);\n },\n\n async restoreRevision(id, revisionId, authorId) {\n return self.revisions.restoreRevision(\n slug,\n revisionId,\n authorId,\n ) as Promise<ContentItem<TData> | null>;\n },\n\n getDiff(oldVersion, newVersion) {\n return self.revisions.computeDiff(oldVersion, newVersion);\n },\n };\n }\n\n /**\n * Run scheduled content publisher for all registered collections.\n */\n async processScheduledContent(\n now: Date = new Date(),\n ): Promise<ContentItem[]> {\n const published: ContentItem[] = [];\n for (const coll of this.collections.values()) {\n const res = await this.lifecycle.processScheduledContent(coll.slug, now);\n published.push(...res);\n }\n return published;\n }\n}\n\n/**\n * Factory helper to create a configured CMSEngine instance.\n */\nexport function createCMSEngine(\n config?: Partial<CMSConfig>,\n storage?: CMSStorageAdapter,\n hooks?: HooksManager,\n): CMSEngine {\n return new CMSEngine(config, storage, hooks);\n}\n","/**\n * @azlib/cms - Modular Plugin Architecture & Extension Interfaces\n */\n\nimport type { CMSEngine } from \"./engine.js\";\nimport type {\n CollectionConfig,\n FieldDefinition,\n TaxonomyConfig,\n} from \"./types.js\";\nimport type { HooksManager } from \"./hooks.js\";\nimport type { OptionsManager } from \"./options.js\";\nimport type { CMSStorageAdapter } from \"../storage/storage-contract.js\";\nimport type { RBACManager } from \"../auth/rbac.js\";\nimport type { MediaManager } from \"../media/media-manager.js\";\nimport type { TaxonomyManager } from \"../taxonomy/taxonomy.js\";\nimport type { RevisionManager } from \"../content/revisions.js\";\nimport type { ContentLifecycle } from \"../content/lifecycle.js\";\n\nexport interface RouteContext {\n readonly params: Record<string, string>;\n readonly url: URL;\n readonly engine: CMSEngine;\n}\n\nexport type CustomRouteHandler = (\n request: Request,\n context: RouteContext,\n) => Promise<Response> | Response;\n\nexport interface CMSPluginContext {\n readonly engine: CMSEngine;\n readonly hooks: HooksManager;\n readonly storage: CMSStorageAdapter;\n readonly options: OptionsManager;\n readonly taxonomies: TaxonomyManager;\n readonly media: MediaManager;\n readonly rbac: RBACManager;\n readonly revisions: RevisionManager;\n readonly lifecycle: ContentLifecycle;\n\n /**\n * Register a new collection dynamically.\n */\n registerCollection(config: CollectionConfig): void;\n\n /**\n * Extend an existing collection with additional field definitions.\n */\n extendCollection(\n collectionSlug: string,\n fields: readonly FieldDefinition[],\n ): void;\n\n /**\n * Register a new taxonomy dynamically.\n */\n registerTaxonomy(config: TaxonomyConfig): void;\n\n /**\n * Register a custom Web Standard HTTP route on the CMS router.\n */\n registerRoute(\n method: string,\n path: string,\n handler: CustomRouteHandler,\n ): void;\n}\n\nexport interface CMSPlugin {\n /**\n * Unique name of the plugin (e.g. \"@azlib/cms-plugin-seo\", \"audit-log\").\n */\n readonly name: string;\n\n /**\n * Optional semantic version string.\n */\n readonly version?: string;\n\n /**\n * Optional human-readable description.\n */\n readonly description?: string;\n\n /**\n * Declarative new collections provided by this plugin.\n */\n readonly collections?: readonly CollectionConfig[];\n\n /**\n * Declarative new taxonomies provided by this plugin.\n */\n readonly taxonomies?: readonly TaxonomyConfig[];\n\n /**\n * Declarative field extensions to inject into existing collections.\n * Maps collection slug -> array of field definitions.\n */\n readonly extendCollections?: Record<string, readonly FieldDefinition[]>;\n\n /**\n * Setup hook called when the plugin is registered with the engine.\n * Allows programmatic registration of hooks, routes, services, and schema extensions.\n */\n setup?: (context: CMSPluginContext) => void | Promise<void>;\n\n /**\n * Lifecycle hook executed during cms.init().\n */\n onInit?: (engine: CMSEngine) => void | Promise<void>;\n\n /**\n * Lifecycle hook executed during cms.close().\n */\n onClose?: (engine: CMSEngine) => void | Promise<void>;\n}\n\n/**\n * Type-safe helper for authoring reusable CMS plugins and plugin factories.\n */\nexport function definePlugin<TOptions = void>(\n factory: (options: TOptions) => CMSPlugin,\n): (options: TOptions) => CMSPlugin {\n return factory;\n}\n","/**\n * @azlib/cms - Universal Web Standard HTTP API Router (Request -> Response)\n */\n\nimport type { CMSEngine } from \"../core/engine.js\";\nimport type { CustomRouteHandler, RouteContext } from \"../core/plugin.js\";\n\ninterface CustomRouteEntry {\n method: string;\n path: string;\n keys: string[];\n regex: RegExp;\n handler: CustomRouteHandler;\n}\n\nfunction compilePath(path: string): { regex: RegExp; keys: string[] } {\n const keys: string[] = [];\n const pattern = path.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => {\n keys.push(key);\n return \"([^/]+)\";\n });\n return {\n regex: new RegExp(`^${pattern}$`),\n keys,\n };\n}\n\nfunction matchRoute(\n entry: { regex: RegExp; keys: string[] },\n pathname: string,\n): Record<string, string> | null {\n const match = pathname.match(entry.regex);\n if (!match) return null;\n const params: Record<string, string> = {};\n for (let i = 0; i < entry.keys.length; i++) {\n params[entry.keys[i]] = decodeURIComponent(match[i + 1]);\n }\n return params;\n}\n\nfunction jsonResponse(\n data: unknown,\n status = 200,\n headers: HeadersInit = {},\n): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n ...headers,\n },\n });\n}\n\nexport class CMSRouter {\n private localRoutes: CustomRouteEntry[] = [];\n\n constructor(private engine: CMSEngine) {}\n\n /**\n * Register a custom Web Standard route on the router.\n */\n registerRoute(\n method: string,\n path: string,\n handler: CustomRouteHandler,\n ): this {\n const { regex, keys } = compilePath(path);\n this.localRoutes.push({\n method: method.toUpperCase(),\n path,\n regex,\n keys,\n handler,\n });\n return this;\n }\n\n /**\n * Universal Web Standards request handler.\n */\n async handle(request: Request): Promise<Response> {\n const url = new URL(request.url);\n const pathname = url.pathname;\n const method = request.method.toUpperCase();\n\n // CORS preflight\n if (method === \"OPTIONS\") {\n return new Response(null, {\n status: 204,\n headers: {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, Authorization\",\n },\n });\n }\n\n try {\n // 1. Cron / Scheduled content runner: POST /api/cron/scheduled\n if (pathname === \"/api/cron/scheduled\" && method === \"POST\") {\n const published = await this.engine.processScheduledContent();\n return jsonResponse({\n success: true,\n publishedCount: published.length,\n items: published,\n });\n }\n\n // 2. Options API: /api/options(/.*)?\n if (pathname.startsWith(\"/api/options\")) {\n return this.handleOptions(pathname, method, url, request);\n }\n\n // 3. Taxonomies API: /api/taxonomies(/.*)?\n if (pathname.startsWith(\"/api/taxonomies\")) {\n return this.handleTaxonomies(pathname, method, url, request);\n }\n\n // 4. Media API: /api/media(/.*)?\n if (pathname.startsWith(\"/api/media\")) {\n return this.handleMedia(pathname, method, url, request);\n }\n\n // 5. Content API: /api/content/:collection(/.*)?\n if (pathname.startsWith(\"/api/content\")) {\n return this.handleContent(pathname, method, url, request);\n }\n\n // 6. Custom Routes registered on CMSRouter or CMSEngine\n const customResponse = await this.handleCustomRoute(\n pathname,\n method,\n url,\n request,\n );\n if (customResponse) {\n return customResponse;\n }\n\n // 404 Not Found for unmatched routes\n return jsonResponse({ error: \"Endpoint not found\", path: pathname }, 404);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return jsonResponse({ error: message }, 500);\n }\n }\n\n private async handleCustomRoute(\n pathname: string,\n method: string,\n url: URL,\n request: Request,\n ): Promise<Response | null> {\n // Check routes registered directly on CMSRouter\n for (const route of this.localRoutes) {\n if (route.method === method) {\n const params = matchRoute(route, pathname);\n if (params !== null) {\n const context: RouteContext = { params, url, engine: this.engine };\n return await route.handler(request, context);\n }\n }\n }\n\n // Check routes registered on CMSEngine (e.g. by plugins)\n const engineRoutes = this.engine.getCustomRoutes().get(method);\n if (engineRoutes) {\n for (const [pathPattern, handler] of engineRoutes) {\n const compiled = compilePath(pathPattern);\n const params = matchRoute(compiled, pathname);\n if (params !== null) {\n const context: RouteContext = { params, url, engine: this.engine };\n return await handler(request, context);\n }\n }\n }\n\n return null;\n }\n\n private async handleContent(\n pathname: string,\n method: string,\n url: URL,\n request: Request,\n ): Promise<Response> {\n const parts = pathname\n .replace(/^\\/api\\/content\\/?/, \"\")\n .split(\"/\")\n .filter(Boolean);\n const collectionSlug = parts[0];\n\n if (!collectionSlug) {\n return jsonResponse(\n {\n collections: this.engine.getCollections().map((c) => ({\n slug: c.slug,\n label: c.label,\n hierarchical: c.hierarchical,\n })),\n },\n 200,\n );\n }\n\n const coll = this.engine.collection(collectionSlug);\n\n // GET /api/content/:collection -> List\n if (parts.length === 1 && method === \"GET\") {\n const status = url.searchParams.get(\"status\") || undefined;\n const search = url.searchParams.get(\"search\") || undefined;\n const limit = url.searchParams.has(\"limit\")\n ? Number(url.searchParams.get(\"limit\"))\n : undefined;\n const offset = url.searchParams.has(\"offset\")\n ? Number(url.searchParams.get(\"offset\"))\n : undefined;\n const termIds = url.searchParams.has(\"termIds\")\n ? url.searchParams.get(\"termIds\")!.split(\",\")\n : undefined;\n\n const result = await coll.find({\n status: status as unknown as undefined,\n search,\n limit,\n offset,\n termIds,\n });\n\n return jsonResponse(result);\n }\n\n // POST /api/content/:collection -> Create\n if (parts.length === 1 && method === \"POST\") {\n const body = await request.json();\n const created = await coll.create(body);\n return jsonResponse(created, 201);\n }\n\n const idOrSlug = parts[1];\n\n // GET /api/content/:collection/:id/revisions\n if (parts.length === 3 && parts[2] === \"revisions\" && method === \"GET\") {\n const revs = await coll.getRevisions(idOrSlug);\n return jsonResponse(revs);\n }\n\n // POST /api/content/:collection/:id/restore/:revisionId\n if (parts.length === 4 && parts[2] === \"restore\" && method === \"POST\") {\n const revisionId = parts[3];\n const restored = await coll.restoreRevision(idOrSlug, revisionId);\n if (!restored) {\n return jsonResponse(\n { error: \"Revision or content item not found\" },\n 404,\n );\n }\n return jsonResponse(restored);\n }\n\n // GET /api/content/:collection/:idOrSlug\n if (parts.length === 2 && method === \"GET\") {\n const bySlug = url.searchParams.get(\"by\") === \"slug\";\n let item = bySlug\n ? await coll.findBySlug(idOrSlug)\n : await coll.findById(idOrSlug);\n if (!item && !bySlug) {\n // Fallback search by slug\n item = await coll.findBySlug(idOrSlug);\n }\n if (!item) return jsonResponse({ error: \"Content item not found\" }, 404);\n return jsonResponse(item);\n }\n\n // PUT /api/content/:collection/:id\n if (parts.length === 2 && method === \"PUT\") {\n const body = await request.json();\n const updated = await coll.update(idOrSlug, body);\n if (!updated)\n return jsonResponse({ error: \"Content item not found\" }, 404);\n return jsonResponse(updated);\n }\n\n // DELETE /api/content/:collection/:id\n if (parts.length === 2 && method === \"DELETE\") {\n const deleted = await coll.delete(idOrSlug);\n if (!deleted)\n return jsonResponse({ error: \"Content item not found\" }, 404);\n return jsonResponse({ success: true, id: idOrSlug });\n }\n\n return jsonResponse({ error: \"Method not allowed\" }, 405);\n }\n\n private async handleTaxonomies(\n pathname: string,\n method: string,\n url: URL,\n request: Request,\n ): Promise<Response> {\n const parts = pathname\n .replace(/^\\/api\\/taxonomies\\/?/, \"\")\n .split(\"/\")\n .filter(Boolean);\n\n // GET /api/taxonomies\n if (parts.length === 0 && method === \"GET\") {\n return jsonResponse(this.engine.taxonomies.getTaxonomies());\n }\n\n const taxonomySlug = parts[0];\n\n // GET /api/taxonomies/:taxonomy/terms\n if (parts.length === 2 && parts[1] === \"terms\" && method === \"GET\") {\n if (url.searchParams.get(\"tree\") === \"true\") {\n const tree = await this.engine.taxonomies.getTermTree(taxonomySlug);\n return jsonResponse(tree);\n }\n const terms = await this.engine.taxonomies.getTerms(taxonomySlug);\n return jsonResponse(terms);\n }\n\n // POST /api/taxonomies/:taxonomy/terms\n if (parts.length === 2 && parts[1] === \"terms\" && method === \"POST\") {\n const body = await request.json();\n const term = await this.engine.taxonomies.createTerm(taxonomySlug, body);\n return jsonResponse(term, 201);\n }\n\n // GET /api/taxonomies/:taxonomy/terms/:id\n if (parts.length === 3 && parts[1] === \"terms\" && method === \"GET\") {\n const term = await this.engine.taxonomies.getTermById(parts[2]);\n if (!term) return jsonResponse({ error: \"Term not found\" }, 404);\n return jsonResponse(term);\n }\n\n // PUT /api/taxonomies/:taxonomy/terms/:id\n if (parts.length === 3 && parts[1] === \"terms\" && method === \"PUT\") {\n const body = await request.json();\n const updated = await this.engine.taxonomies.updateTerm(parts[2], body);\n if (!updated) return jsonResponse({ error: \"Term not found\" }, 404);\n return jsonResponse(updated);\n }\n\n // DELETE /api/taxonomies/:taxonomy/terms/:id\n if (parts.length === 3 && parts[1] === \"terms\" && method === \"DELETE\") {\n const deleted = await this.engine.taxonomies.deleteTerm(parts[2]);\n if (!deleted) return jsonResponse({ error: \"Term not found\" }, 404);\n return jsonResponse({ success: true, id: parts[2] });\n }\n\n return jsonResponse({ error: \"Endpoint not found\" }, 404);\n }\n\n private async handleMedia(\n pathname: string,\n method: string,\n url: URL,\n request: Request,\n ): Promise<Response> {\n const parts = pathname\n .replace(/^\\/api\\/media\\/?/, \"\")\n .split(\"/\")\n .filter(Boolean);\n\n // GET /api/media\n if (parts.length === 0 && method === \"GET\") {\n const search = url.searchParams.get(\"search\") || undefined;\n const mimeType = url.searchParams.get(\"mimeType\") || undefined;\n const limit = url.searchParams.has(\"limit\")\n ? Number(url.searchParams.get(\"limit\"))\n : undefined;\n const offset = url.searchParams.has(\"offset\")\n ? Number(url.searchParams.get(\"offset\"))\n : undefined;\n\n const mediaList = await this.engine.media.find({\n search,\n mimeType,\n limit,\n offset,\n });\n return jsonResponse(mediaList);\n }\n\n // POST /api/media\n if (parts.length === 0 && method === \"POST\") {\n const body = await request.json();\n const media = await this.engine.media.upload(body);\n return jsonResponse(media, 201);\n }\n\n const id = parts[0];\n\n // GET /api/media/:id\n if (parts.length === 1 && method === \"GET\") {\n const media = await this.engine.media.get(id);\n if (!media) return jsonResponse({ error: \"Media not found\" }, 404);\n return jsonResponse(media);\n }\n\n // PUT /api/media/:id\n if (parts.length === 1 && method === \"PUT\") {\n const body = await request.json();\n const updated = await this.engine.media.updateMetadata(id, body);\n if (!updated) return jsonResponse({ error: \"Media not found\" }, 404);\n return jsonResponse(updated);\n }\n\n // DELETE /api/media/:id\n if (parts.length === 1 && method === \"DELETE\") {\n const deleted = await this.engine.media.delete(id);\n if (!deleted) return jsonResponse({ error: \"Media not found\" }, 404);\n return jsonResponse({ success: true, id });\n }\n\n return jsonResponse({ error: \"Method not allowed\" }, 405);\n }\n\n private async handleOptions(\n pathname: string,\n method: string,\n url: URL,\n request: Request,\n ): Promise<Response> {\n const key = pathname.replace(/^\\/api\\/options\\/?/, \"\");\n\n // GET /api/options\n if (!key && method === \"GET\") {\n const namespace = url.searchParams.get(\"namespace\") || undefined;\n const all = await this.engine.options.getAll(namespace);\n return jsonResponse(all);\n }\n\n // GET /api/options/:key\n if (key && method === \"GET\") {\n const val = await this.engine.options.get(key);\n if (val === undefined)\n return jsonResponse({ error: \"Option not found\" }, 404);\n return jsonResponse({ key, value: val });\n }\n\n // PUT /api/options/:key\n if (key && method === \"PUT\") {\n const body = await request.json();\n const item = await this.engine.options.set(key, body.value, {\n autoload: body.autoload,\n namespace: body.namespace,\n });\n return jsonResponse(item);\n }\n\n // DELETE /api/options/:key\n if (key && method === \"DELETE\") {\n const deleted = await this.engine.options.delete(key);\n if (!deleted) return jsonResponse({ error: \"Option not found\" }, 404);\n return jsonResponse({ success: true, key });\n }\n\n return jsonResponse({ error: \"Method not allowed\" }, 405);\n }\n}\n\nexport function createCMSRouter(engine: CMSEngine): CMSRouter {\n return new CMSRouter(engine);\n}\n","/**\n * @azlib/cms - Headless Client SDK\n */\n\nimport type { CMSEngine } from \"../core/engine.js\";\nimport type {\n ContentItem,\n ContentQueryOptions,\n MediaItem,\n PaginatedResult,\n TermItem,\n TermTreeItem,\n} from \"../core/types.js\";\n\nexport interface CMSClientOptions {\n engine?: CMSEngine;\n baseUrl?: string;\n fetch?: typeof globalThis.fetch;\n headers?: Record<string, string>;\n}\n\nexport interface ClientCollectionApi<\n TData extends Record<string, unknown> = Record<string, unknown>,\n> {\n find(\n options?: ContentQueryOptions,\n ): Promise<PaginatedResult<ContentItem<TData>>>;\n findById(id: string): Promise<ContentItem<TData> | null>;\n findBySlug(slug: string): Promise<ContentItem<TData> | null>;\n create(data: Record<string, unknown>): Promise<ContentItem<TData>>;\n update(\n id: string,\n data: Record<string, unknown>,\n ): Promise<ContentItem<TData> | null>;\n delete(id: string): Promise<boolean>;\n}\n\nexport class CMSClient {\n private engine?: CMSEngine;\n private baseUrl?: string;\n private fetchFn: typeof globalThis.fetch;\n private headers: Record<string, string>;\n\n constructor(options: CMSClientOptions) {\n this.engine = options.engine;\n this.baseUrl = options.baseUrl?.replace(/\\/+$/, \"\");\n this.fetchFn = options.fetch ?? globalThis.fetch?.bind(globalThis);\n this.headers = {\n \"Content-Type\": \"application/json\",\n ...(options.headers || {}),\n };\n }\n\n collection<TData extends Record<string, unknown> = Record<string, unknown>>(\n slug: string,\n ): ClientCollectionApi<TData> {\n const self = this;\n\n // Fast direct engine execution mode\n if (this.engine) {\n const coll = this.engine.collection<TData>(slug);\n return {\n find: (opts) => coll.find(opts),\n findById: (id) => coll.findById(id),\n findBySlug: (s) => coll.findBySlug(s),\n create: (data) => coll.create(data),\n update: (id, data) => coll.update(id, data),\n delete: (id) => coll.delete(id),\n };\n }\n\n // Remote HTTP fetch mode\n return {\n async find(options = {}) {\n const params = new URLSearchParams();\n if (options.status) {\n const statuses = Array.isArray(options.status)\n ? options.status.join(\",\")\n : options.status;\n params.set(\"status\", statuses);\n }\n if (options.search) params.set(\"search\", options.search);\n if (options.limit !== undefined)\n params.set(\"limit\", String(options.limit));\n if (options.offset !== undefined)\n params.set(\"offset\", String(options.offset));\n if (options.termIds && options.termIds.length > 0) {\n params.set(\"termIds\", options.termIds.join(\",\"));\n }\n\n const queryStr = params.toString() ? `?${params.toString()}` : \"\";\n return self.request<PaginatedResult<ContentItem<TData>>>(\n `/api/content/${slug}${queryStr}`,\n );\n },\n\n async findById(id: string) {\n return self.request<ContentItem<TData> | null>(\n `/api/content/${slug}/${id}`,\n );\n },\n\n async findBySlug(contentSlug: string) {\n return self.request<ContentItem<TData> | null>(\n `/api/content/${slug}/${contentSlug}?by=slug`,\n );\n },\n\n async create(data: Record<string, unknown>) {\n return self.request<ContentItem<TData>>(`/api/content/${slug}`, {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n },\n\n async update(id: string, data: Record<string, unknown>) {\n return self.request<ContentItem<TData> | null>(\n `/api/content/${slug}/${id}`,\n {\n method: \"PUT\",\n body: JSON.stringify(data),\n },\n );\n },\n\n async delete(id: string) {\n const res = await self.request<{ success: boolean }>(\n `/api/content/${slug}/${id}`,\n {\n method: \"DELETE\",\n },\n );\n return Boolean(res?.success);\n },\n };\n }\n\n readonly taxonomies = {\n getTerms: async (taxonomy: string): Promise<TermItem[]> => {\n if (this.engine) {\n return this.engine.taxonomies.getTerms(taxonomy);\n }\n return this.request<TermItem[]>(`/api/taxonomies/${taxonomy}/terms`);\n },\n\n getTree: async (taxonomy: string): Promise<TermTreeItem[]> => {\n if (this.engine) {\n return this.engine.taxonomies.getTermTree(taxonomy);\n }\n return this.request<TermTreeItem[]>(\n `/api/taxonomies/${taxonomy}/terms?tree=true`,\n );\n },\n };\n\n readonly media = {\n find: async (options?: {\n search?: string;\n limit?: number;\n }): Promise<PaginatedResult<MediaItem>> => {\n if (this.engine) {\n return this.engine.media.find(options);\n }\n const params = new URLSearchParams();\n if (options?.search) params.set(\"search\", options.search);\n if (options?.limit) params.set(\"limit\", String(options.limit));\n const q = params.toString() ? `?${params.toString()}` : \"\";\n return this.request<PaginatedResult<MediaItem>>(`/api/media${q}`);\n },\n\n get: async (id: string): Promise<MediaItem | null> => {\n if (this.engine) {\n return this.engine.media.get(id);\n }\n return this.request<MediaItem | null>(`/api/media/${id}`);\n },\n };\n\n readonly options = {\n get: async <T = unknown>(\n key: string,\n defaultValue?: T,\n ): Promise<T | undefined> => {\n if (this.engine) {\n return this.engine.options.get<T>(key, defaultValue);\n }\n try {\n const res = await this.request<{ key: string; value: T }>(\n `/api/options/${key}`,\n );\n return res?.value ?? defaultValue;\n } catch {\n return defaultValue;\n }\n },\n };\n\n private async request<T>(endpoint: string, init?: RequestInit): Promise<T> {\n if (!this.baseUrl) {\n throw new Error(\n `[CMSClient] baseUrl must be provided when connecting to a remote CMS API.`,\n );\n }\n const url = `${this.baseUrl}${endpoint}`;\n const res = await this.fetchFn(url, {\n ...init,\n headers: {\n ...this.headers,\n ...(init?.headers || {}),\n },\n });\n\n if (!res.ok) {\n if (res.status === 404) return null as unknown as T;\n const body = await res.text();\n throw new Error(`[CMSClient] HTTP ${res.status}: ${body}`);\n }\n\n return res.json() as Promise<T>;\n }\n}\n\nexport function createCmsClient(options: CMSClientOptions): CMSClient {\n return new CMSClient(options);\n}\n"],"mappings":"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"}