@azlib/cms 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -42
- package/dist/index.cjs +3500 -47
- package/dist/index.d.cts +885 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +885 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3444 -48
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs.map
CHANGED
|
@@ -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/core/plugin.ts","../src/api/router.ts","../src/client/cms-client.ts","../src/plugins/ecommerce/schemas.ts","../src/plugins/ecommerce/service.ts","../src/plugins/ecommerce/routes.ts","../src/plugins/ecommerce/client.ts","../src/plugins/ecommerce/index.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 && inputData.title === undefined)\n inputData.title = filteredInput.title;\n if (filteredInput.slug !== undefined && inputData.slug === undefined)\n inputData.slug = filteredInput.slug;\n if (filteredInput.status !== undefined && inputData.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 (\n filteredInput.title !== undefined &&\n filteredInput.data?.title === undefined\n )\n mergedData.title = filteredInput.title;\n else if (existing.title !== undefined && mergedData.title === undefined)\n mergedData.title = existing.title;\n if (\n filteredInput.slug !== undefined &&\n filteredInput.data?.slug === undefined\n )\n mergedData.slug = filteredInput.slug;\n else if (existing.slug !== undefined && mergedData.slug === undefined)\n mergedData.slug = existing.slug;\n if (\n filteredInput.status !== undefined &&\n filteredInput.data?.status === undefined\n )\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): void extends TOptions\n ? (options?: TOptions) => CMSPlugin\n : undefined extends TOptions\n ? (options?: TOptions) => CMSPlugin\n : (options: TOptions) => CMSPlugin {\n return factory as any;\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 /**\n * Access underlying CMSEngine instance when in in-process mode.\n */\n getEngine(): CMSEngine | undefined {\n return this.engine;\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 /**\n * Perform an HTTP request against the CMS API (available in remote mode).\n */\n 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","/**\n * @azlib/cms - Built-in E-commerce Declarative Content Schemas & Taxonomies\n */\n\nimport type { CollectionConfig, TaxonomyConfig } from \"../../core/types.js\";\nimport { collection, fields } from \"../../content/schema.js\";\nimport type { EcommercePluginOptions } from \"./types.js\";\n\n/**\n * Creates the collection configuration for Products.\n */\nexport function createProductCollection(\n options: EcommercePluginOptions = {},\n): CollectionConfig {\n const slug = options.productCollectionSlug ?? \"products\";\n const catSlug = options.categoriesTaxonomySlug ?? \"product_categories\";\n const tagSlug = options.tagsTaxonomySlug ?? \"product_tags\";\n const brandSlug = options.brandsTaxonomySlug ?? \"product_brands\";\n const defaultCurrency = options.defaultCurrency ?? \"USD\";\n\n return collection({\n slug,\n label: \"Products\",\n singularLabel: \"Product\",\n description: \"Catalog products with pricing, inventory, images, and variants\",\n timestamps: true,\n revisions: true,\n draftable: true,\n taxonomies: [catSlug, tagSlug, brandSlug],\n defaultSort: {\n field: \"createdAt\",\n direction: \"desc\",\n },\n fields: [\n fields.text({\n name: \"title\",\n label: \"Product Title\",\n required: true,\n }),\n fields.slug({\n from: \"title\",\n unique: true,\n }),\n fields.text({\n name: \"sku\",\n label: \"SKU\",\n description: \"Stock Keeping Unit identifier\",\n }),\n fields.number({\n name: \"price\",\n label: \"Price\",\n required: true,\n min: 0,\n }),\n fields.number({\n name: \"compareAtPrice\",\n label: \"Compare At Price\",\n description: \"Original retail price for showing strike-through discounts\",\n min: 0,\n }),\n fields.number({\n name: \"costPrice\",\n label: \"Cost Price\",\n description: \"Wholesale or production cost for margin tracking\",\n min: 0,\n }),\n fields.text({\n name: \"currency\",\n label: \"Currency\",\n defaultValue: defaultCurrency,\n }),\n fields.number({\n name: \"stock\",\n label: \"Inventory Quantity\",\n defaultValue: 0,\n min: 0,\n }),\n fields.boolean({\n name: \"trackInventory\",\n label: \"Track Inventory\",\n defaultValue: options.inventoryManagement ?? true,\n }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"draft\", \"published\", \"out_of_stock\", \"archived\"],\n defaultValue: \"draft\",\n }),\n fields.richText({\n name: \"description\",\n label: \"Full Description\",\n }),\n fields.text({\n name: \"shortDescription\",\n label: \"Short Description\",\n }),\n fields.image({\n name: \"featuredImage\",\n label: \"Featured Image\",\n }),\n fields.json({\n name: \"gallery\",\n label: \"Image Gallery\",\n defaultValue: [],\n }),\n fields.json({\n name: \"variants\",\n label: \"Product Variants\",\n defaultValue: [],\n }),\n fields.json({\n name: \"attributes\",\n label: \"Specifications / Attributes\",\n defaultValue: {},\n }),\n fields.number({\n name: \"weight\",\n label: \"Weight\",\n min: 0,\n }),\n ],\n });\n}\n\n/**\n * Creates the collection configuration for Discounts / Coupons.\n */\nexport function createDiscountCollection(\n options: EcommercePluginOptions = {},\n): CollectionConfig {\n const slug = options.discountCollectionSlug ?? \"discounts\";\n\n return collection({\n slug,\n label: \"Discounts\",\n singularLabel: \"Discount\",\n description: \"Promotional discount codes and coupons\",\n timestamps: true,\n revisions: true,\n draftable: false,\n defaultSort: {\n field: \"createdAt\",\n direction: \"desc\",\n },\n fields: [\n fields.text({\n name: \"title\",\n label: \"Discount Name\",\n required: true,\n }),\n fields.text({\n name: \"code\",\n label: \"Coupon Code\",\n required: true,\n unique: true,\n }),\n fields.select({\n name: \"discountType\",\n label: \"Discount Type\",\n options: [\"percentage\", \"fixed_amount\", \"free_shipping\"],\n defaultValue: \"percentage\",\n }),\n fields.number({\n name: \"value\",\n label: \"Discount Value\",\n required: true,\n min: 0,\n }),\n fields.number({\n name: \"minOrderAmount\",\n label: \"Minimum Order Amount\",\n min: 0,\n }),\n fields.number({\n name: \"maxDiscountAmount\",\n label: \"Maximum Discount Cap\",\n min: 0,\n }),\n fields.number({\n name: \"maxUses\",\n label: \"Maximum Uses\",\n min: 1,\n }),\n fields.number({\n name: \"usedCount\",\n label: \"Times Used\",\n defaultValue: 0,\n min: 0,\n }),\n fields.date({\n name: \"startDate\",\n label: \"Start Date\",\n }),\n fields.date({\n name: \"endDate\",\n label: \"Expiration Date\",\n }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"active\", \"disabled\", \"expired\"],\n defaultValue: \"active\",\n }),\n fields.json({\n name: \"appliesToProductIds\",\n label: \"Specific Product IDs\",\n defaultValue: [],\n }),\n fields.json({\n name: \"appliesToCategoryIds\",\n label: \"Specific Category Term IDs\",\n defaultValue: [],\n }),\n ],\n });\n}\n\n/**\n * Creates the collection configuration for Orders.\n */\nexport function createOrderCollection(\n options: EcommercePluginOptions = {},\n): CollectionConfig {\n const slug = options.orderCollectionSlug ?? \"orders\";\n const defaultCurrency = options.defaultCurrency ?? \"USD\";\n\n return collection({\n slug,\n label: \"Orders\",\n singularLabel: \"Order\",\n description: \"Customer orders, status lifecycle, and line items\",\n timestamps: true,\n revisions: true,\n draftable: false,\n defaultSort: {\n field: \"createdAt\",\n direction: \"desc\",\n },\n fields: [\n fields.text({\n name: \"orderNumber\",\n label: \"Order Number\",\n required: true,\n unique: true,\n }),\n fields.text({\n name: \"customerEmail\",\n label: \"Customer Email\",\n required: true,\n }),\n fields.text({\n name: \"customerName\",\n label: \"Customer Name\",\n }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\n \"pending\",\n \"paid\",\n \"processing\",\n \"shipped\",\n \"delivered\",\n \"cancelled\",\n \"refunded\",\n ],\n defaultValue: \"pending\",\n }),\n fields.text({\n name: \"currency\",\n label: \"Currency\",\n defaultValue: defaultCurrency,\n }),\n fields.json({\n name: \"items\",\n label: \"Line Items\",\n defaultValue: [],\n }),\n fields.number({\n name: \"subtotal\",\n label: \"Subtotal\",\n defaultValue: 0,\n min: 0,\n }),\n fields.number({\n name: \"discountTotal\",\n label: \"Discount Total\",\n defaultValue: 0,\n min: 0,\n }),\n fields.text({\n name: \"discountCode\",\n label: \"Discount Code\",\n }),\n fields.number({\n name: \"shippingTotal\",\n label: \"Shipping Total\",\n defaultValue: 0,\n min: 0,\n }),\n fields.number({\n name: \"taxTotal\",\n label: \"Tax Total\",\n defaultValue: 0,\n min: 0,\n }),\n fields.number({\n name: \"total\",\n label: \"Grand Total\",\n defaultValue: 0,\n min: 0,\n }),\n fields.json({\n name: \"shippingAddress\",\n label: \"Shipping Address\",\n }),\n fields.json({\n name: \"billingAddress\",\n label: \"Billing Address\",\n }),\n fields.text({\n name: \"paymentMethod\",\n label: \"Payment Method\",\n }),\n fields.text({\n name: \"notes\",\n label: \"Notes\",\n }),\n ],\n });\n}\n\n/**\n * Creates the standard e-commerce taxonomies: product categories, tags, and brands.\n */\nexport function createEcommerceTaxonomies(\n options: EcommercePluginOptions = {},\n): TaxonomyConfig[] {\n const productSlug = options.productCollectionSlug ?? \"products\";\n const catSlug = options.categoriesTaxonomySlug ?? \"product_categories\";\n const tagSlug = options.tagsTaxonomySlug ?? \"product_tags\";\n const brandSlug = options.brandsTaxonomySlug ?? \"product_brands\";\n\n return [\n {\n slug: catSlug,\n label: \"Product Categories\",\n singularLabel: \"Product Category\",\n hierarchical: true,\n postTypes: [productSlug],\n description: \"Hierarchical categories and catalog collections for organizing products\",\n },\n {\n slug: tagSlug,\n label: \"Product Tags\",\n singularLabel: \"Product Tag\",\n hierarchical: false,\n postTypes: [productSlug],\n description: \"Flat keyword tags for filtering products\",\n },\n {\n slug: brandSlug,\n label: \"Brands\",\n singularLabel: \"Brand\",\n hierarchical: false,\n postTypes: [productSlug],\n description: \"Product manufacturers or brand labels\",\n },\n ];\n}\n","/**\n * @azlib/cms - Built-in E-commerce Service Engine\n */\n\nimport type { CMSEngine, CollectionService } from \"../../core/engine.js\";\nimport type { MediaItem, PaginatedResult, TermItem, TermTreeItem } from \"../../core/types.js\";\nimport type {\n CartCalculationInput,\n CartCalculationResult,\n CreateDiscountInput,\n CreateOrderInput,\n CreateProductInput,\n DiscountData,\n DiscountItem,\n DiscountValidationResult,\n EcommercePluginOptions,\n EcommerceProductQuery,\n OrderData,\n OrderItem,\n OrderLineItem,\n OrderStatus,\n ProductData,\n ProductImage,\n ProductItem,\n UpdateProductInput,\n} from \"./types.js\";\n\nexport class EcommerceService {\n readonly productSlug: string;\n readonly discountSlug: string;\n readonly orderSlug: string;\n readonly categoriesTaxonomy: string;\n readonly tagsTaxonomy: string;\n readonly brandsTaxonomy: string;\n readonly defaultCurrency: string;\n readonly inventoryManagement: boolean;\n\n constructor(\n readonly engine: CMSEngine,\n readonly options: EcommercePluginOptions = {},\n ) {\n this.productSlug = options.productCollectionSlug ?? \"products\";\n this.discountSlug = options.discountCollectionSlug ?? \"discounts\";\n this.orderSlug = options.orderCollectionSlug ?? \"orders\";\n this.categoriesTaxonomy =\n options.categoriesTaxonomySlug ?? \"product_categories\";\n this.tagsTaxonomy = options.tagsTaxonomySlug ?? \"product_tags\";\n this.brandsTaxonomy = options.brandsTaxonomySlug ?? \"product_brands\";\n this.defaultCurrency = options.defaultCurrency ?? \"USD\";\n this.inventoryManagement = options.inventoryManagement ?? true;\n }\n\n // ---------------------------------------------------------------------------\n // Products Management\n // ---------------------------------------------------------------------------\n\n private get productsCollection(): CollectionService<ProductData> {\n return this.engine.collection<ProductData>(this.productSlug);\n }\n\n private get discountsCollection(): CollectionService<DiscountData> {\n return this.engine.collection<DiscountData>(this.discountSlug);\n }\n\n private get ordersCollection(): CollectionService<OrderData> {\n return this.engine.collection<OrderData>(this.orderSlug);\n }\n\n /**\n * Create a new product in the catalog.\n */\n async createProduct(\n input: CreateProductInput,\n authorId?: string | null,\n ): Promise<ProductItem> {\n const productData: ProductData = {\n price: input.price,\n compareAtPrice: input.compareAtPrice,\n costPrice: input.costPrice,\n sku: input.sku,\n currency: input.currency ?? this.defaultCurrency,\n stock: input.stock ?? 0,\n trackInventory: input.trackInventory ?? this.inventoryManagement,\n status: input.status ?? \"draft\",\n description: input.description,\n shortDescription: input.shortDescription,\n featuredImage: input.featuredImage,\n gallery: input.gallery ?? [],\n variants: input.variants ?? [],\n attributes: input.attributes ?? {},\n weight: input.weight,\n };\n\n const product = await this.productsCollection.create(\n {\n title: input.title,\n slug: input.slug,\n status: input.status === \"published\" ? \"published\" : \"draft\",\n data: productData,\n },\n authorId,\n );\n\n // Assign categories if provided\n if (input.categoryIds && input.categoryIds.length > 0) {\n await this.engine.taxonomies.assignTerms(product.id, input.categoryIds);\n }\n\n // Assign tags if provided\n if (input.tagIds && input.tagIds.length > 0) {\n await this.engine.taxonomies.assignTerms(product.id, input.tagIds);\n }\n\n // Assign brands if provided\n if (input.brandIds && input.brandIds.length > 0) {\n await this.engine.taxonomies.assignTerms(product.id, input.brandIds);\n }\n\n await this.engine.hooks.doAction(\"ecommerce.product_created\", product);\n return product;\n }\n\n /**\n * Update an existing product.\n */\n async updateProduct(\n id: string,\n input: UpdateProductInput,\n authorId?: string | null,\n ): Promise<ProductItem | null> {\n const existing = await this.getProduct(id);\n if (!existing) return null;\n\n const updatedData: ProductData = {\n ...existing.data,\n ...(input.price !== undefined ? { price: input.price } : {}),\n ...(input.compareAtPrice !== undefined\n ? { compareAtPrice: input.compareAtPrice }\n : {}),\n ...(input.costPrice !== undefined ? { costPrice: input.costPrice } : {}),\n ...(input.sku !== undefined ? { sku: input.sku } : {}),\n ...(input.currency !== undefined ? { currency: input.currency } : {}),\n ...(input.stock !== undefined ? { stock: input.stock } : {}),\n ...(input.trackInventory !== undefined\n ? { trackInventory: input.trackInventory }\n : {}),\n ...(input.status !== undefined ? { status: input.status } : {}),\n ...(input.description !== undefined\n ? { description: input.description }\n : {}),\n ...(input.shortDescription !== undefined\n ? { shortDescription: input.shortDescription }\n : {}),\n ...(input.featuredImage !== undefined\n ? { featuredImage: input.featuredImage }\n : {}),\n ...(input.gallery !== undefined ? { gallery: input.gallery } : {}),\n ...(input.variants !== undefined ? { variants: input.variants } : {}),\n ...(input.attributes !== undefined\n ? { attributes: input.attributes }\n : {}),\n ...(input.weight !== undefined ? { weight: input.weight } : {}),\n };\n\n const updated = await this.productsCollection.update(\n id,\n {\n ...(input.title ? { title: input.title } : {}),\n ...(input.slug ? { slug: input.slug } : {}),\n ...(input.status === \"published\"\n ? { status: \"published\" }\n : input.status\n ? { status: \"draft\" }\n : {}),\n data: updatedData,\n },\n authorId,\n );\n\n if (updated) {\n if (input.categoryIds) {\n await this.engine.taxonomies.assignTerms(id, input.categoryIds);\n }\n if (input.tagIds) {\n await this.engine.taxonomies.assignTerms(id, input.tagIds);\n }\n if (input.brandIds) {\n await this.engine.taxonomies.assignTerms(id, input.brandIds);\n }\n await this.engine.hooks.doAction(\"ecommerce.product_updated\", updated);\n }\n\n return updated;\n }\n\n /**\n * Get a product by ID.\n */\n async getProduct(id: string): Promise<ProductItem | null> {\n return this.productsCollection.findById(id);\n }\n\n /**\n * Get a product by its URL slug.\n */\n async getProductBySlug(slug: string): Promise<ProductItem | null> {\n return this.productsCollection.findBySlug(slug);\n }\n\n /**\n * Delete a product by ID.\n */\n async deleteProduct(id: string): Promise<boolean> {\n const deleted = await this.productsCollection.delete(id);\n if (deleted) {\n await this.engine.hooks.doAction(\"ecommerce.product_deleted\", id);\n }\n return deleted;\n }\n\n /**\n * List and filter catalog products.\n */\n async listProducts(\n query: EcommerceProductQuery = {},\n ): Promise<PaginatedResult<ProductItem>> {\n let termIds: string[] | undefined;\n\n // Resolve category slug or ID\n if (query.categorySlug) {\n const term = await this.engine.taxonomies.getTermBySlug(\n this.categoriesTaxonomy,\n query.categorySlug,\n );\n if (term) {\n termIds = [term.id];\n } else {\n return { items: [], total: 0, limit: query.limit ?? 20, offset: query.offset ?? 0, hasMore: false };\n }\n } else if (query.categoryId) {\n termIds = [query.categoryId];\n }\n\n // Resolve tag slug\n if (query.tagSlug) {\n const term = await this.engine.taxonomies.getTermBySlug(\n this.tagsTaxonomy,\n query.tagSlug,\n );\n if (term) {\n termIds = termIds ? [...termIds, term.id] : [term.id];\n }\n }\n\n // Resolve brand slug\n if (query.brandSlug) {\n const term = await this.engine.taxonomies.getTermBySlug(\n this.brandsTaxonomy,\n query.brandSlug,\n );\n if (term) {\n termIds = termIds ? [...termIds, term.id] : [term.id];\n }\n }\n\n const contentStatus =\n query.status === \"draft\"\n ? \"draft\"\n : query.status === \"published\"\n ? \"published\"\n : undefined;\n\n const result = await this.productsCollection.find({\n search: query.search,\n termIds,\n status: contentStatus ?? \"published\",\n limit: query.limit ?? 20,\n offset: query.offset ?? 0,\n orderBy:\n query.orderBy === \"price\" || query.orderBy === \"stock\"\n ? undefined\n : query.orderBy,\n orderDirection: query.orderDirection ?? \"desc\",\n });\n\n let items = result.items;\n\n if (query.status) {\n const statuses = Array.isArray(query.status)\n ? query.status\n : [query.status];\n items = items.filter((p) => statuses.includes(p.data.status));\n }\n\n // Post-filter by price range if specified\n if (query.minPrice !== undefined) {\n items = items.filter((p) => p.data.price >= query.minPrice!);\n }\n if (query.maxPrice !== undefined) {\n items = items.filter((p) => p.data.price <= query.maxPrice!);\n }\n\n // Post-filter by in-stock\n if (query.inStock) {\n items = items.filter(\n (p) => !p.data.trackInventory || p.data.stock > 0,\n );\n }\n\n // Sort by price or stock if requested\n if (query.orderBy === \"price\") {\n items.sort((a, b) =>\n query.orderDirection === \"asc\"\n ? a.data.price - b.data.price\n : b.data.price - a.data.price,\n );\n } else if (query.orderBy === \"stock\") {\n items.sort((a, b) =>\n query.orderDirection === \"asc\"\n ? a.data.stock - b.data.stock\n : b.data.stock - a.data.stock,\n );\n }\n\n return {\n items,\n total: items.length,\n limit: result.limit,\n offset: result.offset,\n hasMore: result.offset + items.length < result.total,\n };\n }\n\n /**\n * Upload and link a product image to its gallery and featured slot.\n */\n async uploadProductImage(\n productId: string,\n file: {\n filename: string;\n mimeType: string;\n sizeBytes: number;\n url?: string;\n altText?: string;\n caption?: string;\n width?: number;\n height?: number;\n isFeatured?: boolean;\n },\n authorId?: string | null,\n ): Promise<{ media: MediaItem; product: ProductItem }> {\n const product = await this.getProduct(productId);\n if (!product) {\n throw new Error(`[EcommerceService] Product '${productId}' not found.`);\n }\n\n // Upload asset via CMS media manager\n const media = await this.engine.media.upload(\n {\n filename: file.filename,\n mimeType: file.mimeType,\n sizeBytes: file.sizeBytes,\n url: file.url,\n altText: file.altText ?? product.title,\n caption: file.caption,\n width: file.width,\n height: file.height,\n },\n authorId,\n );\n\n const gallery: ProductImage[] = [...(product.data.gallery || [])];\n gallery.push({\n id: media.id,\n url: media.url,\n altText: media.altText,\n caption: media.caption,\n width: media.width,\n height: media.height,\n });\n\n const isFeatured = file.isFeatured ?? !product.data.featuredImage;\n\n const updated = await this.productsCollection.update(productId, {\n data: {\n ...product.data,\n gallery,\n ...(isFeatured ? { featuredImage: media.url } : {}),\n },\n });\n\n await this.engine.hooks.doAction(\"ecommerce.product_image_added\", {\n product: updated ?? product,\n media,\n });\n\n return {\n media,\n product: (updated ?? product) as ProductItem,\n };\n }\n\n /**\n * Adjust inventory stock for a product or variant.\n */\n async adjustStock(\n productId: string,\n delta: number,\n variantId?: string,\n ): Promise<ProductItem | null> {\n const product = await this.getProduct(productId);\n if (!product) return null;\n\n if (!product.data.trackInventory) {\n return product;\n }\n\n let newStock = product.data.stock;\n const variants = [...(product.data.variants || [])];\n\n if (variantId) {\n const idx = variants.findIndex((v) => v.id === variantId);\n if (idx !== -1) {\n const currentVariantStock = variants[idx].stock ?? 0;\n const updatedVariantStock = Math.max(0, currentVariantStock + delta);\n variants[idx] = { ...variants[idx], stock: updatedVariantStock };\n }\n } else {\n newStock = Math.max(0, product.data.stock + delta);\n }\n\n const newStatus =\n newStock === 0 && product.data.status === \"published\"\n ? \"out_of_stock\"\n : product.data.status === \"out_of_stock\" && newStock > 0\n ? \"published\"\n : product.data.status;\n\n const updated = await this.productsCollection.update(productId, {\n data: {\n ...product.data,\n stock: newStock,\n variants,\n status: newStatus,\n },\n });\n\n await this.engine.hooks.doAction(\"ecommerce.stock_changed\", {\n product: updated ?? product,\n delta,\n variantId,\n oldStock: product.data.stock,\n newStock,\n });\n\n return updated;\n }\n\n // ---------------------------------------------------------------------------\n // Catalog & Categories\n // ---------------------------------------------------------------------------\n\n /**\n * Create a catalog category in the hierarchical category taxonomy.\n */\n async createCategory(input: {\n name: string;\n slug?: string;\n parentId?: string | null;\n description?: string;\n meta?: Record<string, unknown>;\n }): Promise<TermItem> {\n return this.engine.taxonomies.createTerm(this.categoriesTaxonomy, input);\n }\n\n /**\n * Get all catalog categories.\n */\n async getCategories(options?: {\n parentId?: string | null;\n }): Promise<TermItem[]> {\n return this.engine.taxonomies.getTerms(this.categoriesTaxonomy, options);\n }\n\n /**\n * Get full hierarchical catalog category tree.\n */\n async getCategoryTree(): Promise<TermTreeItem[]> {\n return this.engine.taxonomies.getTermTree(this.categoriesTaxonomy);\n }\n\n /**\n * Assign category IDs to a product.\n */\n async assignProductCategory(\n productId: string,\n categoryIds: string | string[],\n ): Promise<void> {\n const ids = Array.isArray(categoryIds) ? categoryIds : [categoryIds];\n await this.engine.taxonomies.assignTerms(productId, ids);\n }\n\n /**\n * Get assigned categories for a product.\n */\n async getProductCategories(productId: string): Promise<TermItem[]> {\n return this.engine.taxonomies.getContentTerms(\n productId,\n this.categoriesTaxonomy,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Discounts & Coupons\n // ---------------------------------------------------------------------------\n\n /**\n * Create a promotional coupon / discount code.\n */\n async createDiscount(\n input: CreateDiscountInput,\n authorId?: string | null,\n ): Promise<DiscountItem> {\n const normalizedCode = input.code.trim().toUpperCase();\n\n const discountData: DiscountData = {\n code: normalizedCode,\n discountType: input.discountType,\n value: input.value,\n minOrderAmount: input.minOrderAmount,\n maxDiscountAmount: input.maxDiscountAmount,\n maxUses: input.maxUses,\n usedCount: 0,\n startDate: input.startDate,\n endDate: input.endDate,\n status: input.status ?? \"active\",\n appliesToProductIds: input.appliesToProductIds ?? [],\n appliesToCategoryIds: input.appliesToCategoryIds ?? [],\n };\n\n const discount = await this.discountsCollection.create(\n {\n title: input.title,\n slug: normalizedCode.toLowerCase(),\n status: \"published\",\n data: discountData,\n },\n authorId,\n );\n\n await this.engine.hooks.doAction(\"ecommerce.discount_created\", discount);\n return discount;\n }\n\n /**\n * Find a discount code.\n */\n async getDiscountByCode(code: string): Promise<DiscountItem | null> {\n const normalized = code.trim().toUpperCase();\n const result = await this.discountsCollection.find({\n limit: 100,\n });\n\n const match = result.items.find(\n (d) => d.data.code?.toUpperCase() === normalized,\n );\n return match ?? null;\n }\n\n /**\n * Validate a discount coupon against cart items and order subtotal.\n */\n async validateDiscount(\n code: string,\n cartSubtotal: number,\n productIds: string[] = [],\n ): Promise<DiscountValidationResult> {\n const normalized = code.trim().toUpperCase();\n const discount = await this.getDiscountByCode(normalized);\n\n if (!discount) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: `Discount code '${code}' not found.`,\n };\n }\n\n const { data } = discount;\n\n if (data.status !== \"active\") {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: \"Discount code is currently inactive.\",\n };\n }\n\n const now = Date.now();\n if (data.startDate && new Date(data.startDate).getTime() > now) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: \"Discount code is not yet active.\",\n };\n }\n\n if (data.endDate && new Date(data.endDate).getTime() < now) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: \"Discount code has expired.\",\n };\n }\n\n if (data.maxUses !== undefined && data.usedCount >= data.maxUses) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: \"Discount code usage limit reached.\",\n };\n }\n\n if (data.minOrderAmount !== undefined && cartSubtotal < data.minOrderAmount) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: `Minimum order amount of ${data.minOrderAmount} required for this coupon.`,\n };\n }\n\n // Check product specific restriction if defined\n if (\n data.appliesToProductIds &&\n data.appliesToProductIds.length > 0 &&\n productIds.length > 0\n ) {\n const hasMatchingProduct = productIds.some((id) =>\n data.appliesToProductIds?.includes(id),\n );\n if (!hasMatchingProduct) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: \"Coupon is not applicable to any products in your cart.\",\n };\n }\n }\n\n // Calculate discount amount\n let discountAmount = 0;\n if (data.discountType === \"percentage\") {\n discountAmount = (cartSubtotal * data.value) / 100;\n if (data.maxDiscountAmount) {\n discountAmount = Math.min(discountAmount, data.maxDiscountAmount);\n }\n } else if (data.discountType === \"fixed_amount\") {\n discountAmount = Math.min(data.value, cartSubtotal);\n } else if (data.discountType === \"free_shipping\") {\n discountAmount = 0; // Handled during shipping calculation\n }\n\n // Apply hook filter for external price overrides\n discountAmount = await this.engine.hooks.applyFilters(\n \"ecommerce.apply_discount\",\n discountAmount,\n { discount, cartSubtotal },\n );\n\n return {\n valid: true,\n code: normalized,\n discountAmount: Math.round(discountAmount * 100) / 100,\n discountType: data.discountType,\n discount,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Cart & Checkout Calculations\n // ---------------------------------------------------------------------------\n\n /**\n * Calculate cart subtotals, apply discounts, shipping, and taxes.\n */\n async calculateCart(\n input: CartCalculationInput,\n ): Promise<CartCalculationResult> {\n const lineItems: OrderLineItem[] = [];\n let subtotal = 0;\n const productIds: string[] = [];\n\n for (const item of input.items) {\n const product = await this.getProduct(item.productId);\n if (!product) {\n throw new Error(\n `[EcommerceService] Product '${item.productId}' not found.`,\n );\n }\n\n productIds.push(product.id);\n\n let price = product.data.price;\n let sku = product.data.sku;\n let title = product.title ?? \"Product\";\n let availableStock = product.data.stock;\n let image = product.data.featuredImage;\n\n if (item.variantId && product.data.variants) {\n const variant = product.data.variants.find(\n (v) => v.id === item.variantId,\n );\n if (variant) {\n price = variant.price ?? price;\n sku = variant.sku ?? sku;\n title = `${title} (${variant.title})`;\n availableStock = variant.stock ?? availableStock;\n image = variant.image ?? image;\n }\n }\n\n // Verify stock availability\n if (\n this.inventoryManagement &&\n product.data.trackInventory &&\n availableStock < item.quantity\n ) {\n throw new Error(\n `[EcommerceService] Insufficient stock for '${title}'. Available: ${availableStock}, Requested: ${item.quantity}.`,\n );\n }\n\n const itemSubtotal = Math.round(price * item.quantity * 100) / 100;\n subtotal += itemSubtotal;\n\n lineItems.push({\n productId: product.id,\n variantId: item.variantId,\n title,\n sku,\n price,\n quantity: item.quantity,\n subtotal: itemSubtotal,\n image,\n });\n }\n\n subtotal = Math.round(subtotal * 100) / 100;\n\n // Apply discount code\n let discountTotal = 0;\n let discountType: string | undefined;\n if (input.discountCode) {\n const validation = await this.validateDiscount(\n input.discountCode,\n subtotal,\n productIds,\n );\n if (validation.valid) {\n discountTotal = validation.discountAmount;\n discountType = validation.discountType;\n }\n }\n\n // Shipping calculation\n let shippingTotal =\n input.shippingCost ?? this.options.defaultShippingCost ?? 0;\n if (discountType === \"free_shipping\") {\n shippingTotal = 0;\n }\n\n // Tax calculation\n const taxRate = input.taxRate ?? this.options.defaultTaxRate ?? 0;\n const taxableAmount = Math.max(0, subtotal - discountTotal);\n const taxTotal = Math.round(taxableAmount * taxRate * 100) / 100;\n\n // Grand total\n const total =\n Math.round((taxableAmount + shippingTotal + taxTotal) * 100) / 100;\n\n const result: CartCalculationResult = {\n items: lineItems,\n subtotal,\n discountTotal,\n discountCode: input.discountCode,\n shippingTotal,\n taxTotal,\n total,\n currency: this.defaultCurrency,\n };\n\n return this.engine.hooks.applyFilters(\n \"ecommerce.calculate_totals\",\n result,\n input,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Orders Management\n // ---------------------------------------------------------------------------\n\n /**\n * Place a new order with cart validation, inventory deduction, and coupon counter updates.\n */\n async createOrder(\n input: CreateOrderInput,\n authorId?: string | null,\n ): Promise<OrderItem> {\n const calc = await this.calculateCart({\n items: input.items,\n discountCode: input.discountCode,\n shippingCost: input.shippingCost,\n taxRate: input.taxRate,\n });\n\n // Generate unique order number: ORD-YYYYMMDD-XXXX\n const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, \"\");\n const randomSuffix = Math.random().toString(36).substring(2, 6).toUpperCase();\n const orderNumber = `ORD-${dateStr}-${randomSuffix}`;\n\n // Decrement stock for purchased items\n if (this.inventoryManagement) {\n for (const item of input.items) {\n await this.adjustStock(item.productId, -item.quantity, item.variantId);\n }\n }\n\n // Increment discount usage counter if applied\n if (input.discountCode) {\n const discount = await this.getDiscountByCode(input.discountCode);\n if (discount) {\n await this.discountsCollection.update(discount.id, {\n data: {\n ...discount.data,\n usedCount: (discount.data.usedCount || 0) + 1,\n },\n });\n }\n }\n\n const orderData: OrderData = {\n orderNumber,\n customerEmail: input.customerEmail,\n customerName: input.customerName,\n status: \"pending\",\n currency: calc.currency,\n items: calc.items,\n subtotal: calc.subtotal,\n discountTotal: calc.discountTotal,\n discountCode: calc.discountCode,\n shippingTotal: calc.shippingTotal,\n taxTotal: calc.taxTotal,\n total: calc.total,\n shippingAddress: input.shippingAddress,\n billingAddress: input.billingAddress,\n paymentMethod: input.paymentMethod,\n notes: input.notes,\n };\n\n const order = await this.ordersCollection.create(\n {\n title: `Order #${orderNumber}`,\n slug: orderNumber.toLowerCase(),\n status: \"published\",\n data: orderData,\n },\n authorId,\n );\n\n await this.engine.hooks.doAction(\"ecommerce.order_created\", order);\n return order;\n }\n\n /**\n * Get order by ID.\n */\n async getOrder(id: string): Promise<OrderItem | null> {\n return this.ordersCollection.findById(id);\n }\n\n /**\n * Get order by order number.\n */\n async getOrderByNumber(orderNumber: string): Promise<OrderItem | null> {\n const result = await this.ordersCollection.find({ limit: 100 });\n const match = result.items.find(\n (o) => o.data.orderNumber?.toUpperCase() === orderNumber.toUpperCase(),\n );\n return match ?? null;\n }\n\n /**\n * Update the status of an order (e.g. pending -> paid -> shipped).\n */\n async updateOrderStatus(\n id: string,\n status: OrderStatus,\n note?: string,\n ): Promise<OrderItem | null> {\n const existing = await this.getOrder(id);\n if (!existing) return null;\n\n const oldStatus = existing.data.status;\n const updated = await this.ordersCollection.update(\n id,\n {\n data: {\n ...existing.data,\n status,\n },\n },\n undefined,\n note,\n );\n\n if (updated) {\n await this.engine.hooks.doAction(\"ecommerce.order_status_changed\", {\n order: updated,\n oldStatus,\n newStatus: status,\n note,\n });\n }\n\n return updated;\n }\n}\n","/**\n * @azlib/cms - Built-in E-commerce Web Standard HTTP API Routes\n */\n\nimport type { CMSPluginContext } from \"../../core/plugin.js\";\nimport type { EcommerceService } from \"./service.js\";\nimport type {\n CartCalculationInput,\n CreateDiscountInput,\n CreateOrderInput,\n CreateProductInput,\n EcommercePluginOptions,\n OrderStatus,\n UpdateProductInput,\n} from \"./types.js\";\n\nfunction json(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Access-Control-Allow-Origin\": \"*\",\n },\n });\n}\n\nfunction badRequest(message: string): Response {\n return json({ error: message }, 400);\n}\n\nfunction notFound(message: string): Response {\n return json({ error: message }, 404);\n}\n\nexport function registerEcommerceRoutes(\n ctx: CMSPluginContext,\n service: EcommerceService,\n options: EcommercePluginOptions = {},\n): void {\n const prefix = (options.apiPrefix ?? \"/api/ecommerce\").replace(/\\/+$/, \"\");\n\n // ---------------------------------------------------------------------------\n // Products Endpoints\n // ---------------------------------------------------------------------------\n\n // GET /api/ecommerce/products\n ctx.registerRoute(\"GET\", `${prefix}/products`, async (_req, { url }) => {\n try {\n const categorySlug = url.searchParams.get(\"category\") ?? undefined;\n const categoryId = url.searchParams.get(\"categoryId\") ?? undefined;\n const tagSlug = url.searchParams.get(\"tag\") ?? undefined;\n const brandSlug = url.searchParams.get(\"brand\") ?? undefined;\n const search = url.searchParams.get(\"search\") ?? undefined;\n const statusParam = url.searchParams.get(\"status\") as any;\n const inStock = url.searchParams.get(\"inStock\") === \"true\";\n\n const minPriceStr = url.searchParams.get(\"minPrice\");\n const maxPriceStr = url.searchParams.get(\"maxPrice\");\n const minPrice = minPriceStr ? parseFloat(minPriceStr) : undefined;\n const maxPrice = maxPriceStr ? parseFloat(maxPriceStr) : undefined;\n\n const orderBy = url.searchParams.get(\"orderBy\") as any;\n const orderDirection = (url.searchParams.get(\"orderDirection\") ?? \"desc\") as \"asc\" | \"desc\";\n\n const limitStr = url.searchParams.get(\"limit\");\n const offsetStr = url.searchParams.get(\"offset\");\n const limit = limitStr ? parseInt(limitStr, 10) : 20;\n const offset = offsetStr ? parseInt(offsetStr, 10) : 0;\n\n const results = await service.listProducts({\n categorySlug,\n categoryId,\n tagSlug,\n brandSlug,\n search,\n status: statusParam,\n inStock,\n minPrice,\n maxPrice,\n orderBy,\n orderDirection,\n limit,\n offset,\n });\n\n return json(results);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // GET /api/ecommerce/products/:id\n ctx.registerRoute(\"GET\", `${prefix}/products/:id`, async (_req, { params, url }) => {\n const id = params.id;\n const by = url.searchParams.get(\"by\");\n\n let product = null;\n if (by === \"slug\") {\n product = await service.getProductBySlug(id);\n } else {\n product = await service.getProduct(id);\n if (!product) {\n product = await service.getProductBySlug(id);\n }\n }\n\n if (!product) {\n return notFound(`Product '${id}' not found`);\n }\n\n return json(product);\n });\n\n // POST /api/ecommerce/products\n ctx.registerRoute(\"POST\", `${prefix}/products`, async (req) => {\n try {\n const body = (await req.json()) as CreateProductInput;\n if (!body.title) {\n return badRequest(\"Product 'title' is required.\");\n }\n if (body.price === undefined || body.price < 0) {\n return badRequest(\"Valid product 'price' is required.\");\n }\n\n const product = await service.createProduct(body);\n return json(product, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // PUT /api/ecommerce/products/:id\n ctx.registerRoute(\"PUT\", `${prefix}/products/:id`, async (req, { params }) => {\n try {\n const body = (await req.json()) as UpdateProductInput;\n const updated = await service.updateProduct(params.id, body);\n if (!updated) {\n return notFound(`Product '${params.id}' not found.`);\n }\n return json(updated);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // DELETE /api/ecommerce/products/:id\n ctx.registerRoute(\"DELETE\", `${prefix}/products/:id`, async (_req, { params }) => {\n const deleted = await service.deleteProduct(params.id);\n if (!deleted) {\n return notFound(`Product '${params.id}' not found.`);\n }\n return json({ success: true, id: params.id });\n });\n\n // POST /api/ecommerce/products/:id/images\n ctx.registerRoute(\"POST\", `${prefix}/products/:id/images`, async (req, { params }) => {\n try {\n const body = await req.json();\n if (!body.filename || !body.mimeType) {\n return badRequest(\"'filename' and 'mimeType' are required.\");\n }\n\n const result = await service.uploadProductImage(params.id, {\n filename: body.filename,\n mimeType: body.mimeType,\n sizeBytes: body.sizeBytes ?? 0,\n url: body.url,\n altText: body.altText,\n caption: body.caption,\n width: body.width,\n height: body.height,\n isFeatured: body.isFeatured,\n });\n\n return json(result, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // ---------------------------------------------------------------------------\n // Categories & Catalog Endpoints\n // ---------------------------------------------------------------------------\n\n // GET /api/ecommerce/categories\n ctx.registerRoute(\"GET\", `${prefix}/categories`, async (_req, { url }) => {\n try {\n const isTree = url.searchParams.get(\"tree\") === \"true\";\n if (isTree) {\n const tree = await service.getCategoryTree();\n return json(tree);\n }\n const parentId = url.searchParams.get(\"parentId\");\n const list = await service.getCategories({\n parentId: parentId === \"null\" ? null : parentId ?? undefined,\n });\n return json(list);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // POST /api/ecommerce/categories\n ctx.registerRoute(\"POST\", `${prefix}/categories`, async (req) => {\n try {\n const body = await req.json();\n if (!body.name) {\n return badRequest(\"Category 'name' is required.\");\n }\n const category = await service.createCategory(body);\n return json(category, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // ---------------------------------------------------------------------------\n // Discounts & Coupons Endpoints\n // ---------------------------------------------------------------------------\n\n if (options.enableDiscounts !== false) {\n // POST /api/ecommerce/discounts\n ctx.registerRoute(\"POST\", `${prefix}/discounts`, async (req) => {\n try {\n const body = (await req.json()) as CreateDiscountInput;\n if (!body.title || !body.code) {\n return badRequest(\"'title' and 'code' are required.\");\n }\n if (body.value === undefined || body.value < 0) {\n return badRequest(\"Valid discount 'value' is required.\");\n }\n const discount = await service.createDiscount(body);\n return json(discount, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // POST /api/ecommerce/discounts/validate\n ctx.registerRoute(\"POST\", `${prefix}/discounts/validate`, async (req) => {\n try {\n const body = await req.json();\n if (!body.code) {\n return badRequest(\"Discount 'code' is required.\");\n }\n const subtotal = Number(body.subtotal ?? 0);\n const productIds = Array.isArray(body.productIds) ? body.productIds : [];\n\n const result = await service.validateDiscount(\n body.code,\n subtotal,\n productIds,\n );\n return json(result);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n }\n\n // ---------------------------------------------------------------------------\n // Cart & Order Endpoints\n // ---------------------------------------------------------------------------\n\n // POST /api/ecommerce/cart/calculate\n ctx.registerRoute(\"POST\", `${prefix}/cart/calculate`, async (req) => {\n try {\n const body = (await req.json()) as CartCalculationInput;\n if (!body.items || !Array.isArray(body.items) || body.items.length === 0) {\n return badRequest(\"'items' array is required and must not be empty.\");\n }\n const calculation = await service.calculateCart(body);\n return json(calculation);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n if (options.enableOrders !== false) {\n // POST /api/ecommerce/orders\n ctx.registerRoute(\"POST\", `${prefix}/orders`, async (req) => {\n try {\n const body = (await req.json()) as CreateOrderInput;\n if (!body.customerEmail) {\n return badRequest(\"'customerEmail' is required.\");\n }\n if (!body.items || !Array.isArray(body.items) || body.items.length === 0) {\n return badRequest(\"'items' array is required.\");\n }\n\n const order = await service.createOrder(body);\n return json(order, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // GET /api/ecommerce/orders/:id\n ctx.registerRoute(\"GET\", `${prefix}/orders/:id`, async (_req, { params, url }) => {\n const id = params.id;\n const by = url.searchParams.get(\"by\");\n\n let order = null;\n if (by === \"number\") {\n order = await service.getOrderByNumber(id);\n } else {\n order = await service.getOrder(id);\n if (!order) {\n order = await service.getOrderByNumber(id);\n }\n }\n\n if (!order) {\n return notFound(`Order '${id}' not found.`);\n }\n\n return json(order);\n });\n\n // PATCH /api/ecommerce/orders/:id/status\n ctx.registerRoute(\"PATCH\", `${prefix}/orders/:id/status`, async (req, { params }) => {\n try {\n const body = await req.json();\n if (!body.status) {\n return badRequest(\"New 'status' is required.\");\n }\n const updated = await service.updateOrderStatus(\n params.id,\n body.status as OrderStatus,\n body.note,\n );\n if (!updated) {\n return notFound(`Order '${params.id}' not found.`);\n }\n return json(updated);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n }\n}\n","/**\n * @azlib/cms - Built-in E-commerce Headless Client Extension\n */\n\nimport type { CMSClient } from \"../../client/cms-client.js\";\nimport type { MediaItem, PaginatedResult, TermItem, TermTreeItem } from \"../../core/types.js\";\nimport { EcommerceService } from \"./service.js\";\nimport type {\n CartCalculationInput,\n CartCalculationResult,\n CreateDiscountInput,\n CreateOrderInput,\n CreateProductInput,\n DiscountItem,\n DiscountValidationResult,\n EcommercePluginOptions,\n EcommerceProductQuery,\n OrderItem,\n OrderStatus,\n ProductItem,\n UpdateProductInput,\n} from \"./types.js\";\n\nexport class EcommerceClient {\n private service?: EcommerceService;\n private prefix: string;\n\n constructor(\n private client: CMSClient,\n private options: EcommercePluginOptions = {},\n ) {\n this.prefix = (options.apiPrefix ?? \"/api/ecommerce\").replace(/\\/+$/, \"\");\n const engine = client.getEngine();\n if (engine) {\n this.service = new EcommerceService(engine, options);\n }\n }\n\n readonly products = {\n find: async (\n query: EcommerceProductQuery = {},\n ): Promise<PaginatedResult<ProductItem>> => {\n if (this.service) {\n return this.service.listProducts(query);\n }\n const params = new URLSearchParams();\n if (query.categorySlug) params.set(\"category\", query.categorySlug);\n if (query.categoryId) params.set(\"categoryId\", query.categoryId);\n if (query.tagSlug) params.set(\"tag\", query.tagSlug);\n if (query.brandSlug) params.set(\"brand\", query.brandSlug);\n if (query.search) params.set(\"search\", query.search);\n if (query.inStock) params.set(\"inStock\", \"true\");\n if (query.minPrice !== undefined)\n params.set(\"minPrice\", String(query.minPrice));\n if (query.maxPrice !== undefined)\n params.set(\"maxPrice\", String(query.maxPrice));\n if (query.orderBy) params.set(\"orderBy\", query.orderBy);\n if (query.orderDirection)\n params.set(\"orderDirection\", query.orderDirection);\n if (query.limit !== undefined) params.set(\"limit\", String(query.limit));\n if (query.offset !== undefined) params.set(\"offset\", String(query.offset));\n\n const q = params.toString() ? `?${params.toString()}` : \"\";\n return this.client.request<PaginatedResult<ProductItem>>(\n `${this.prefix}/products${q}`,\n );\n },\n\n get: async (\n idOrSlug: string,\n by?: \"id\" | \"slug\",\n ): Promise<ProductItem | null> => {\n if (this.service) {\n return by === \"slug\"\n ? this.service.getProductBySlug(idOrSlug)\n : this.service.getProduct(idOrSlug);\n }\n const query = by ? `?by=${by}` : \"\";\n return this.client.request<ProductItem | null>(\n `${this.prefix}/products/${encodeURIComponent(idOrSlug)}${query}`,\n );\n },\n\n create: async (data: CreateProductInput): Promise<ProductItem> => {\n if (this.service) {\n return this.service.createProduct(data);\n }\n return this.client.request<ProductItem>(`${this.prefix}/products`, {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n },\n\n update: async (\n id: string,\n data: UpdateProductInput,\n ): Promise<ProductItem | null> => {\n if (this.service) {\n return this.service.updateProduct(id, data);\n }\n return this.client.request<ProductItem | null>(\n `${this.prefix}/products/${encodeURIComponent(id)}`,\n {\n method: \"PUT\",\n body: JSON.stringify(data),\n },\n );\n },\n\n delete: async (id: string): Promise<boolean> => {\n if (this.service) {\n return this.service.deleteProduct(id);\n }\n const res = await this.client.request<{ success: boolean }>(\n `${this.prefix}/products/${encodeURIComponent(id)}`,\n {\n method: \"DELETE\",\n },\n );\n return Boolean(res?.success);\n },\n\n uploadImage: async (\n productId: string,\n file: {\n filename: string;\n mimeType: string;\n sizeBytes: number;\n url?: string;\n altText?: string;\n caption?: string;\n width?: number;\n height?: number;\n isFeatured?: boolean;\n },\n ): Promise<{ media: MediaItem; product: ProductItem }> => {\n if (this.service) {\n return this.service.uploadProductImage(productId, file);\n }\n return this.client.request<{ media: MediaItem; product: ProductItem }>(\n `${this.prefix}/products/${encodeURIComponent(productId)}/images`,\n {\n method: \"POST\",\n body: JSON.stringify(file),\n },\n );\n },\n };\n\n readonly categories = {\n list: async (options?: {\n parentId?: string | null;\n }): Promise<TermItem[]> => {\n if (this.service) {\n return this.service.getCategories(options);\n }\n const q = options?.parentId !== undefined ? `?parentId=${options.parentId}` : \"\";\n return this.client.request<TermItem[]>(`${this.prefix}/categories${q}`);\n },\n\n tree: async (): Promise<TermTreeItem[]> => {\n if (this.service) {\n return this.service.getCategoryTree();\n }\n return this.client.request<TermTreeItem[]>(\n `${this.prefix}/categories?tree=true`,\n );\n },\n\n create: async (input: {\n name: string;\n slug?: string;\n parentId?: string | null;\n description?: string;\n }): Promise<TermItem> => {\n if (this.service) {\n return this.service.createCategory(input);\n }\n return this.client.request<TermItem>(`${this.prefix}/categories`, {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n },\n };\n\n readonly discounts = {\n validate: async (\n code: string,\n subtotal: number,\n productIds?: string[],\n ): Promise<DiscountValidationResult> => {\n if (this.service) {\n return this.service.validateDiscount(code, subtotal, productIds);\n }\n return this.client.request<DiscountValidationResult>(\n `${this.prefix}/discounts/validate`,\n {\n method: \"POST\",\n body: JSON.stringify({ code, subtotal, productIds }),\n },\n );\n },\n\n create: async (input: CreateDiscountInput): Promise<DiscountItem> => {\n if (this.service) {\n return this.service.createDiscount(input);\n }\n return this.client.request<DiscountItem>(`${this.prefix}/discounts`, {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n },\n };\n\n readonly cart = {\n calculate: async (\n input: CartCalculationInput,\n ): Promise<CartCalculationResult> => {\n if (this.service) {\n return this.service.calculateCart(input);\n }\n return this.client.request<CartCalculationResult>(\n `${this.prefix}/cart/calculate`,\n {\n method: \"POST\",\n body: JSON.stringify(input),\n },\n );\n },\n };\n\n readonly orders = {\n create: async (input: CreateOrderInput): Promise<OrderItem> => {\n if (this.service) {\n return this.service.createOrder(input);\n }\n return this.client.request<OrderItem>(`${this.prefix}/orders`, {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n },\n\n get: async (\n idOrNumber: string,\n by?: \"id\" | \"number\",\n ): Promise<OrderItem | null> => {\n if (this.service) {\n return by === \"number\"\n ? this.service.getOrderByNumber(idOrNumber)\n : this.service.getOrder(idOrNumber);\n }\n const q = by ? `?by=${by}` : \"\";\n return this.client.request<OrderItem | null>(\n `${this.prefix}/orders/${encodeURIComponent(idOrNumber)}${q}`,\n );\n },\n\n updateStatus: async (\n id: string,\n status: OrderStatus,\n note?: string,\n ): Promise<OrderItem | null> => {\n if (this.service) {\n return this.service.updateOrderStatus(id, status, note);\n }\n return this.client.request<OrderItem | null>(\n `${this.prefix}/orders/${encodeURIComponent(id)}/status`,\n {\n method: \"PATCH\",\n body: JSON.stringify({ status, note }),\n },\n );\n },\n };\n}\n\n/**\n * Get or create an EcommerceClient adapter for a CMSClient.\n */\nexport function getEcommerceClient(\n client: CMSClient,\n options?: EcommercePluginOptions,\n): EcommerceClient {\n return new EcommerceClient(client, options);\n}\n","/**\n * @azlib/cms - Built-in E-commerce Plugin\n */\n\nimport { definePlugin, type CMSPlugin } from \"../../core/plugin.js\";\nimport type { CMSEngine } from \"../../core/engine.js\";\nimport {\n createDiscountCollection,\n createEcommerceTaxonomies,\n createOrderCollection,\n createProductCollection,\n} from \"./schemas.js\";\nimport { EcommerceService } from \"./service.js\";\nimport { registerEcommerceRoutes } from \"./routes.js\";\nimport type { EcommercePluginOptions } from \"./types.js\";\n\nexport * from \"./types.js\";\nexport * from \"./schemas.js\";\nexport * from \"./service.js\";\nexport * from \"./client.js\";\n\n/**\n * Built-in E-commerce plugin factory for @azlib/cms.\n * Equips the CMS engine with product catalogs, hierarchical categories,\n * image uploading, discount coupons, cart calculation, and order tracking.\n */\nexport const ecommercePlugin = definePlugin<EcommercePluginOptions | void>(\n (options: EcommercePluginOptions | void): CMSPlugin => {\n const opts: EcommercePluginOptions = options || {};\n const collections = [createProductCollection(opts)];\n\n if (opts.enableDiscounts !== false) {\n collections.push(createDiscountCollection(opts));\n }\n\n if (opts.enableOrders !== false) {\n collections.push(createOrderCollection(opts));\n }\n\n const taxonomies = createEcommerceTaxonomies(opts);\n\n return {\n name: \"ecommerce\",\n version: \"1.0.0\",\n description:\n \"Built-in E-commerce shopping, products, catalogs, discounts, and orders plugin\",\n collections,\n taxonomies,\n\n setup(ctx) {\n const service = new EcommerceService(ctx.engine, opts);\n // Cache instance on engine for retrieval via getEcommerceService\n (ctx.engine as any).__ecommerceService = service;\n registerEcommerceRoutes(ctx, service, opts);\n },\n };\n },\n);\n\n/**\n * Retrieve the active EcommerceService instance associated with a CMSEngine.\n */\nexport function getEcommerceService(\n engine: CMSEngine,\n options?: EcommercePluginOptions,\n): EcommerceService {\n if ((engine as any).__ecommerceService) {\n return (engine as any).__ecommerceService;\n }\n const service = new EcommerceService(engine, options);\n (engine as any).__ecommerceService = service;\n return service;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["json","badRequest","notFound","json","badRequest","notFound","formulaVal","blob"],"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","../src/plugins/ecommerce/schemas.ts","../src/plugins/ecommerce/service.ts","../src/plugins/ecommerce/routes.ts","../src/plugins/ecommerce/client.ts","../src/plugins/ecommerce/index.ts","../src/plugins/hrms/schemas.ts","../src/plugins/hrms/service.ts","../src/plugins/hrms/routes.ts","../src/plugins/hrms/client.ts","../src/plugins/hrms/index.ts","../src/plugins/transfer/parsers/json.ts","../src/plugins/transfer/parsers/csv.ts","../src/plugins/transfer/parsers/excel.ts","../src/plugins/transfer/parsers/index.ts","../src/plugins/transfer/serializers/json.ts","../src/plugins/transfer/serializers/csv.ts","../src/plugins/transfer/serializers/excel.ts","../src/plugins/transfer/serializers/index.ts","../src/plugins/transfer/inspect.ts","../src/plugins/transfer/mapping.ts","../src/plugins/transfer/validator.ts","../src/plugins/transfer/presets/hrms.ts","../src/plugins/transfer/service.ts","../src/plugins/transfer/routes.ts","../src/plugins/transfer/client.ts","../src/plugins/transfer/index.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 && inputData.title === undefined)\n inputData.title = filteredInput.title;\n if (filteredInput.slug !== undefined && inputData.slug === undefined)\n inputData.slug = filteredInput.slug;\n if (\n filteredInput.status !== undefined &&\n inputData.status === undefined\n )\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 (\n filteredInput.title !== undefined &&\n filteredInput.data?.title === undefined\n )\n mergedData.title = filteredInput.title;\n else if (existing.title !== undefined && mergedData.title === undefined)\n mergedData.title = existing.title;\n if (\n filteredInput.slug !== undefined &&\n filteredInput.data?.slug === undefined\n )\n mergedData.slug = filteredInput.slug;\n else if (existing.slug !== undefined && mergedData.slug === undefined)\n mergedData.slug = existing.slug;\n if (\n filteredInput.status !== undefined &&\n filteredInput.data?.status === undefined\n )\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): void extends TOptions\n ? (options?: TOptions) => CMSPlugin\n : undefined extends TOptions\n ? (options?: TOptions) => CMSPlugin\n : (options: TOptions) => CMSPlugin {\n return factory as any;\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 /**\n * Access underlying CMSEngine instance when in in-process mode.\n */\n getEngine(): CMSEngine | undefined {\n return this.engine;\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 /**\n * Perform an HTTP request against the CMS API (available in remote mode).\n */\n 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","/**\n * @azlib/cms - Built-in E-commerce Declarative Content Schemas & Taxonomies\n */\n\nimport type { CollectionConfig, TaxonomyConfig } from \"../../core/types.js\";\nimport { collection, fields } from \"../../content/schema.js\";\nimport type { EcommercePluginOptions } from \"./types.js\";\n\n/**\n * Creates the collection configuration for Products.\n */\nexport function createProductCollection(\n options: EcommercePluginOptions = {},\n): CollectionConfig {\n const slug = options.productCollectionSlug ?? \"products\";\n const catSlug = options.categoriesTaxonomySlug ?? \"product_categories\";\n const tagSlug = options.tagsTaxonomySlug ?? \"product_tags\";\n const brandSlug = options.brandsTaxonomySlug ?? \"product_brands\";\n const defaultCurrency = options.defaultCurrency ?? \"USD\";\n\n return collection({\n slug,\n label: \"Products\",\n singularLabel: \"Product\",\n description:\n \"Catalog products with pricing, inventory, images, and variants\",\n timestamps: true,\n revisions: true,\n draftable: true,\n taxonomies: [catSlug, tagSlug, brandSlug],\n defaultSort: {\n field: \"createdAt\",\n direction: \"desc\",\n },\n fields: [\n fields.text({\n name: \"title\",\n label: \"Product Title\",\n required: true,\n }),\n fields.slug({\n from: \"title\",\n unique: true,\n }),\n fields.text({\n name: \"sku\",\n label: \"SKU\",\n description: \"Stock Keeping Unit identifier\",\n }),\n fields.number({\n name: \"price\",\n label: \"Price\",\n required: true,\n min: 0,\n }),\n fields.number({\n name: \"compareAtPrice\",\n label: \"Compare At Price\",\n description:\n \"Original retail price for showing strike-through discounts\",\n min: 0,\n }),\n fields.number({\n name: \"costPrice\",\n label: \"Cost Price\",\n description: \"Wholesale or production cost for margin tracking\",\n min: 0,\n }),\n fields.text({\n name: \"currency\",\n label: \"Currency\",\n defaultValue: defaultCurrency,\n }),\n fields.number({\n name: \"stock\",\n label: \"Inventory Quantity\",\n defaultValue: 0,\n min: 0,\n }),\n fields.boolean({\n name: \"trackInventory\",\n label: \"Track Inventory\",\n defaultValue: options.inventoryManagement ?? true,\n }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"draft\", \"published\", \"out_of_stock\", \"archived\"],\n defaultValue: \"draft\",\n }),\n fields.richText({\n name: \"description\",\n label: \"Full Description\",\n }),\n fields.text({\n name: \"shortDescription\",\n label: \"Short Description\",\n }),\n fields.image({\n name: \"featuredImage\",\n label: \"Featured Image\",\n }),\n fields.json({\n name: \"gallery\",\n label: \"Image Gallery\",\n defaultValue: [],\n }),\n fields.json({\n name: \"variants\",\n label: \"Product Variants\",\n defaultValue: [],\n }),\n fields.json({\n name: \"attributes\",\n label: \"Specifications / Attributes\",\n defaultValue: {},\n }),\n fields.number({\n name: \"weight\",\n label: \"Weight\",\n min: 0,\n }),\n ],\n });\n}\n\n/**\n * Creates the collection configuration for Discounts / Coupons.\n */\nexport function createDiscountCollection(\n options: EcommercePluginOptions = {},\n): CollectionConfig {\n const slug = options.discountCollectionSlug ?? \"discounts\";\n\n return collection({\n slug,\n label: \"Discounts\",\n singularLabel: \"Discount\",\n description: \"Promotional discount codes and coupons\",\n timestamps: true,\n revisions: true,\n draftable: false,\n defaultSort: {\n field: \"createdAt\",\n direction: \"desc\",\n },\n fields: [\n fields.text({\n name: \"title\",\n label: \"Discount Name\",\n required: true,\n }),\n fields.text({\n name: \"code\",\n label: \"Coupon Code\",\n required: true,\n unique: true,\n }),\n fields.select({\n name: \"discountType\",\n label: \"Discount Type\",\n options: [\"percentage\", \"fixed_amount\", \"free_shipping\"],\n defaultValue: \"percentage\",\n }),\n fields.number({\n name: \"value\",\n label: \"Discount Value\",\n required: true,\n min: 0,\n }),\n fields.number({\n name: \"minOrderAmount\",\n label: \"Minimum Order Amount\",\n min: 0,\n }),\n fields.number({\n name: \"maxDiscountAmount\",\n label: \"Maximum Discount Cap\",\n min: 0,\n }),\n fields.number({\n name: \"maxUses\",\n label: \"Maximum Uses\",\n min: 1,\n }),\n fields.number({\n name: \"usedCount\",\n label: \"Times Used\",\n defaultValue: 0,\n min: 0,\n }),\n fields.date({\n name: \"startDate\",\n label: \"Start Date\",\n }),\n fields.date({\n name: \"endDate\",\n label: \"Expiration Date\",\n }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"active\", \"disabled\", \"expired\"],\n defaultValue: \"active\",\n }),\n fields.json({\n name: \"appliesToProductIds\",\n label: \"Specific Product IDs\",\n defaultValue: [],\n }),\n fields.json({\n name: \"appliesToCategoryIds\",\n label: \"Specific Category Term IDs\",\n defaultValue: [],\n }),\n ],\n });\n}\n\n/**\n * Creates the collection configuration for Orders.\n */\nexport function createOrderCollection(\n options: EcommercePluginOptions = {},\n): CollectionConfig {\n const slug = options.orderCollectionSlug ?? \"orders\";\n const defaultCurrency = options.defaultCurrency ?? \"USD\";\n\n return collection({\n slug,\n label: \"Orders\",\n singularLabel: \"Order\",\n description: \"Customer orders, status lifecycle, and line items\",\n timestamps: true,\n revisions: true,\n draftable: false,\n defaultSort: {\n field: \"createdAt\",\n direction: \"desc\",\n },\n fields: [\n fields.text({\n name: \"orderNumber\",\n label: \"Order Number\",\n required: true,\n unique: true,\n }),\n fields.text({\n name: \"customerEmail\",\n label: \"Customer Email\",\n required: true,\n }),\n fields.text({\n name: \"customerName\",\n label: \"Customer Name\",\n }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\n \"pending\",\n \"paid\",\n \"processing\",\n \"shipped\",\n \"delivered\",\n \"cancelled\",\n \"refunded\",\n ],\n defaultValue: \"pending\",\n }),\n fields.text({\n name: \"currency\",\n label: \"Currency\",\n defaultValue: defaultCurrency,\n }),\n fields.json({\n name: \"items\",\n label: \"Line Items\",\n defaultValue: [],\n }),\n fields.number({\n name: \"subtotal\",\n label: \"Subtotal\",\n defaultValue: 0,\n min: 0,\n }),\n fields.number({\n name: \"discountTotal\",\n label: \"Discount Total\",\n defaultValue: 0,\n min: 0,\n }),\n fields.text({\n name: \"discountCode\",\n label: \"Discount Code\",\n }),\n fields.number({\n name: \"shippingTotal\",\n label: \"Shipping Total\",\n defaultValue: 0,\n min: 0,\n }),\n fields.number({\n name: \"taxTotal\",\n label: \"Tax Total\",\n defaultValue: 0,\n min: 0,\n }),\n fields.number({\n name: \"total\",\n label: \"Grand Total\",\n defaultValue: 0,\n min: 0,\n }),\n fields.json({\n name: \"shippingAddress\",\n label: \"Shipping Address\",\n }),\n fields.json({\n name: \"billingAddress\",\n label: \"Billing Address\",\n }),\n fields.text({\n name: \"paymentMethod\",\n label: \"Payment Method\",\n }),\n fields.text({\n name: \"notes\",\n label: \"Notes\",\n }),\n ],\n });\n}\n\n/**\n * Creates the standard e-commerce taxonomies: product categories, tags, and brands.\n */\nexport function createEcommerceTaxonomies(\n options: EcommercePluginOptions = {},\n): TaxonomyConfig[] {\n const productSlug = options.productCollectionSlug ?? \"products\";\n const catSlug = options.categoriesTaxonomySlug ?? \"product_categories\";\n const tagSlug = options.tagsTaxonomySlug ?? \"product_tags\";\n const brandSlug = options.brandsTaxonomySlug ?? \"product_brands\";\n\n return [\n {\n slug: catSlug,\n label: \"Product Categories\",\n singularLabel: \"Product Category\",\n hierarchical: true,\n postTypes: [productSlug],\n description:\n \"Hierarchical categories and catalog collections for organizing products\",\n },\n {\n slug: tagSlug,\n label: \"Product Tags\",\n singularLabel: \"Product Tag\",\n hierarchical: false,\n postTypes: [productSlug],\n description: \"Flat keyword tags for filtering products\",\n },\n {\n slug: brandSlug,\n label: \"Brands\",\n singularLabel: \"Brand\",\n hierarchical: false,\n postTypes: [productSlug],\n description: \"Product manufacturers or brand labels\",\n },\n ];\n}\n","/**\n * @azlib/cms - Built-in E-commerce Service Engine\n */\n\nimport type { CMSEngine, CollectionService } from \"../../core/engine.js\";\nimport type {\n MediaItem,\n PaginatedResult,\n TermItem,\n TermTreeItem,\n} from \"../../core/types.js\";\nimport type {\n CartCalculationInput,\n CartCalculationResult,\n CreateDiscountInput,\n CreateOrderInput,\n CreateProductInput,\n DiscountData,\n DiscountItem,\n DiscountValidationResult,\n EcommercePluginOptions,\n EcommerceProductQuery,\n OrderData,\n OrderItem,\n OrderLineItem,\n OrderStatus,\n ProductData,\n ProductImage,\n ProductItem,\n UpdateProductInput,\n} from \"./types.js\";\n\nexport class EcommerceService {\n readonly productSlug: string;\n readonly discountSlug: string;\n readonly orderSlug: string;\n readonly categoriesTaxonomy: string;\n readonly tagsTaxonomy: string;\n readonly brandsTaxonomy: string;\n readonly defaultCurrency: string;\n readonly inventoryManagement: boolean;\n\n constructor(\n readonly engine: CMSEngine,\n readonly options: EcommercePluginOptions = {},\n ) {\n this.productSlug = options.productCollectionSlug ?? \"products\";\n this.discountSlug = options.discountCollectionSlug ?? \"discounts\";\n this.orderSlug = options.orderCollectionSlug ?? \"orders\";\n this.categoriesTaxonomy =\n options.categoriesTaxonomySlug ?? \"product_categories\";\n this.tagsTaxonomy = options.tagsTaxonomySlug ?? \"product_tags\";\n this.brandsTaxonomy = options.brandsTaxonomySlug ?? \"product_brands\";\n this.defaultCurrency = options.defaultCurrency ?? \"USD\";\n this.inventoryManagement = options.inventoryManagement ?? true;\n }\n\n // ---------------------------------------------------------------------------\n // Products Management\n // ---------------------------------------------------------------------------\n\n private get productsCollection(): CollectionService<ProductData> {\n return this.engine.collection<ProductData>(this.productSlug);\n }\n\n private get discountsCollection(): CollectionService<DiscountData> {\n return this.engine.collection<DiscountData>(this.discountSlug);\n }\n\n private get ordersCollection(): CollectionService<OrderData> {\n return this.engine.collection<OrderData>(this.orderSlug);\n }\n\n /**\n * Create a new product in the catalog.\n */\n async createProduct(\n input: CreateProductInput,\n authorId?: string | null,\n ): Promise<ProductItem> {\n const productData: ProductData = {\n price: input.price,\n compareAtPrice: input.compareAtPrice,\n costPrice: input.costPrice,\n sku: input.sku,\n currency: input.currency ?? this.defaultCurrency,\n stock: input.stock ?? 0,\n trackInventory: input.trackInventory ?? this.inventoryManagement,\n status: input.status ?? \"draft\",\n description: input.description,\n shortDescription: input.shortDescription,\n featuredImage: input.featuredImage,\n gallery: input.gallery ?? [],\n variants: input.variants ?? [],\n attributes: input.attributes ?? {},\n weight: input.weight,\n };\n\n const product = await this.productsCollection.create(\n {\n title: input.title,\n slug: input.slug,\n status: input.status === \"published\" ? \"published\" : \"draft\",\n data: productData,\n },\n authorId,\n );\n\n // Assign categories if provided\n if (input.categoryIds && input.categoryIds.length > 0) {\n await this.engine.taxonomies.assignTerms(product.id, input.categoryIds);\n }\n\n // Assign tags if provided\n if (input.tagIds && input.tagIds.length > 0) {\n await this.engine.taxonomies.assignTerms(product.id, input.tagIds);\n }\n\n // Assign brands if provided\n if (input.brandIds && input.brandIds.length > 0) {\n await this.engine.taxonomies.assignTerms(product.id, input.brandIds);\n }\n\n await this.engine.hooks.doAction(\"ecommerce.product_created\", product);\n return product;\n }\n\n /**\n * Update an existing product.\n */\n async updateProduct(\n id: string,\n input: UpdateProductInput,\n authorId?: string | null,\n ): Promise<ProductItem | null> {\n const existing = await this.getProduct(id);\n if (!existing) return null;\n\n const updatedData: ProductData = {\n ...existing.data,\n ...(input.price !== undefined ? { price: input.price } : {}),\n ...(input.compareAtPrice !== undefined\n ? { compareAtPrice: input.compareAtPrice }\n : {}),\n ...(input.costPrice !== undefined ? { costPrice: input.costPrice } : {}),\n ...(input.sku !== undefined ? { sku: input.sku } : {}),\n ...(input.currency !== undefined ? { currency: input.currency } : {}),\n ...(input.stock !== undefined ? { stock: input.stock } : {}),\n ...(input.trackInventory !== undefined\n ? { trackInventory: input.trackInventory }\n : {}),\n ...(input.status !== undefined ? { status: input.status } : {}),\n ...(input.description !== undefined\n ? { description: input.description }\n : {}),\n ...(input.shortDescription !== undefined\n ? { shortDescription: input.shortDescription }\n : {}),\n ...(input.featuredImage !== undefined\n ? { featuredImage: input.featuredImage }\n : {}),\n ...(input.gallery !== undefined ? { gallery: input.gallery } : {}),\n ...(input.variants !== undefined ? { variants: input.variants } : {}),\n ...(input.attributes !== undefined\n ? { attributes: input.attributes }\n : {}),\n ...(input.weight !== undefined ? { weight: input.weight } : {}),\n };\n\n const updated = await this.productsCollection.update(\n id,\n {\n ...(input.title ? { title: input.title } : {}),\n ...(input.slug ? { slug: input.slug } : {}),\n ...(input.status === \"published\"\n ? { status: \"published\" }\n : input.status\n ? { status: \"draft\" }\n : {}),\n data: updatedData,\n },\n authorId,\n );\n\n if (updated) {\n if (input.categoryIds) {\n await this.engine.taxonomies.assignTerms(id, input.categoryIds);\n }\n if (input.tagIds) {\n await this.engine.taxonomies.assignTerms(id, input.tagIds);\n }\n if (input.brandIds) {\n await this.engine.taxonomies.assignTerms(id, input.brandIds);\n }\n await this.engine.hooks.doAction(\"ecommerce.product_updated\", updated);\n }\n\n return updated;\n }\n\n /**\n * Get a product by ID.\n */\n async getProduct(id: string): Promise<ProductItem | null> {\n return this.productsCollection.findById(id);\n }\n\n /**\n * Get a product by its URL slug.\n */\n async getProductBySlug(slug: string): Promise<ProductItem | null> {\n return this.productsCollection.findBySlug(slug);\n }\n\n /**\n * Delete a product by ID.\n */\n async deleteProduct(id: string): Promise<boolean> {\n const deleted = await this.productsCollection.delete(id);\n if (deleted) {\n await this.engine.hooks.doAction(\"ecommerce.product_deleted\", id);\n }\n return deleted;\n }\n\n /**\n * List and filter catalog products.\n */\n async listProducts(\n query: EcommerceProductQuery = {},\n ): Promise<PaginatedResult<ProductItem>> {\n let termIds: string[] | undefined;\n\n // Resolve category slug or ID\n if (query.categorySlug) {\n const term = await this.engine.taxonomies.getTermBySlug(\n this.categoriesTaxonomy,\n query.categorySlug,\n );\n if (term) {\n termIds = [term.id];\n } else {\n return {\n items: [],\n total: 0,\n limit: query.limit ?? 20,\n offset: query.offset ?? 0,\n hasMore: false,\n };\n }\n } else if (query.categoryId) {\n termIds = [query.categoryId];\n }\n\n // Resolve tag slug\n if (query.tagSlug) {\n const term = await this.engine.taxonomies.getTermBySlug(\n this.tagsTaxonomy,\n query.tagSlug,\n );\n if (term) {\n termIds = termIds ? [...termIds, term.id] : [term.id];\n }\n }\n\n // Resolve brand slug\n if (query.brandSlug) {\n const term = await this.engine.taxonomies.getTermBySlug(\n this.brandsTaxonomy,\n query.brandSlug,\n );\n if (term) {\n termIds = termIds ? [...termIds, term.id] : [term.id];\n }\n }\n\n const contentStatus =\n query.status === \"draft\"\n ? \"draft\"\n : query.status === \"published\"\n ? \"published\"\n : undefined;\n\n const result = await this.productsCollection.find({\n search: query.search,\n termIds,\n status: contentStatus ?? \"published\",\n limit: query.limit ?? 20,\n offset: query.offset ?? 0,\n orderBy:\n query.orderBy === \"price\" || query.orderBy === \"stock\"\n ? undefined\n : query.orderBy,\n orderDirection: query.orderDirection ?? \"desc\",\n });\n\n let items = result.items;\n\n if (query.status) {\n const statuses = Array.isArray(query.status)\n ? query.status\n : [query.status];\n items = items.filter((p) => statuses.includes(p.data.status));\n }\n\n // Post-filter by price range if specified\n if (query.minPrice !== undefined) {\n items = items.filter((p) => p.data.price >= query.minPrice!);\n }\n if (query.maxPrice !== undefined) {\n items = items.filter((p) => p.data.price <= query.maxPrice!);\n }\n\n // Post-filter by in-stock\n if (query.inStock) {\n items = items.filter((p) => !p.data.trackInventory || p.data.stock > 0);\n }\n\n // Sort by price or stock if requested\n if (query.orderBy === \"price\") {\n items.sort((a, b) =>\n query.orderDirection === \"asc\"\n ? a.data.price - b.data.price\n : b.data.price - a.data.price,\n );\n } else if (query.orderBy === \"stock\") {\n items.sort((a, b) =>\n query.orderDirection === \"asc\"\n ? a.data.stock - b.data.stock\n : b.data.stock - a.data.stock,\n );\n }\n\n return {\n items,\n total: items.length,\n limit: result.limit,\n offset: result.offset,\n hasMore: result.offset + items.length < result.total,\n };\n }\n\n /**\n * Upload and link a product image to its gallery and featured slot.\n */\n async uploadProductImage(\n productId: string,\n file: {\n filename: string;\n mimeType: string;\n sizeBytes: number;\n url?: string;\n altText?: string;\n caption?: string;\n width?: number;\n height?: number;\n isFeatured?: boolean;\n },\n authorId?: string | null,\n ): Promise<{ media: MediaItem; product: ProductItem }> {\n const product = await this.getProduct(productId);\n if (!product) {\n throw new Error(`[EcommerceService] Product '${productId}' not found.`);\n }\n\n // Upload asset via CMS media manager\n const media = await this.engine.media.upload(\n {\n filename: file.filename,\n mimeType: file.mimeType,\n sizeBytes: file.sizeBytes,\n url: file.url,\n altText: file.altText ?? product.title,\n caption: file.caption,\n width: file.width,\n height: file.height,\n },\n authorId,\n );\n\n const gallery: ProductImage[] = [...(product.data.gallery || [])];\n gallery.push({\n id: media.id,\n url: media.url,\n altText: media.altText,\n caption: media.caption,\n width: media.width,\n height: media.height,\n });\n\n const isFeatured = file.isFeatured ?? !product.data.featuredImage;\n\n const updated = await this.productsCollection.update(productId, {\n data: {\n ...product.data,\n gallery,\n ...(isFeatured ? { featuredImage: media.url } : {}),\n },\n });\n\n await this.engine.hooks.doAction(\"ecommerce.product_image_added\", {\n product: updated ?? product,\n media,\n });\n\n return {\n media,\n product: (updated ?? product) as ProductItem,\n };\n }\n\n /**\n * Adjust inventory stock for a product or variant.\n */\n async adjustStock(\n productId: string,\n delta: number,\n variantId?: string,\n ): Promise<ProductItem | null> {\n const product = await this.getProduct(productId);\n if (!product) return null;\n\n if (!product.data.trackInventory) {\n return product;\n }\n\n let newStock = product.data.stock;\n const variants = [...(product.data.variants || [])];\n\n if (variantId) {\n const idx = variants.findIndex((v) => v.id === variantId);\n if (idx !== -1) {\n const currentVariantStock = variants[idx].stock ?? 0;\n const updatedVariantStock = Math.max(0, currentVariantStock + delta);\n variants[idx] = { ...variants[idx], stock: updatedVariantStock };\n }\n } else {\n newStock = Math.max(0, product.data.stock + delta);\n }\n\n const newStatus =\n newStock === 0 && product.data.status === \"published\"\n ? \"out_of_stock\"\n : product.data.status === \"out_of_stock\" && newStock > 0\n ? \"published\"\n : product.data.status;\n\n const updated = await this.productsCollection.update(productId, {\n data: {\n ...product.data,\n stock: newStock,\n variants,\n status: newStatus,\n },\n });\n\n await this.engine.hooks.doAction(\"ecommerce.stock_changed\", {\n product: updated ?? product,\n delta,\n variantId,\n oldStock: product.data.stock,\n newStock,\n });\n\n return updated;\n }\n\n // ---------------------------------------------------------------------------\n // Catalog & Categories\n // ---------------------------------------------------------------------------\n\n /**\n * Create a catalog category in the hierarchical category taxonomy.\n */\n async createCategory(input: {\n name: string;\n slug?: string;\n parentId?: string | null;\n description?: string;\n meta?: Record<string, unknown>;\n }): Promise<TermItem> {\n return this.engine.taxonomies.createTerm(this.categoriesTaxonomy, input);\n }\n\n /**\n * Get all catalog categories.\n */\n async getCategories(options?: {\n parentId?: string | null;\n }): Promise<TermItem[]> {\n return this.engine.taxonomies.getTerms(this.categoriesTaxonomy, options);\n }\n\n /**\n * Get full hierarchical catalog category tree.\n */\n async getCategoryTree(): Promise<TermTreeItem[]> {\n return this.engine.taxonomies.getTermTree(this.categoriesTaxonomy);\n }\n\n /**\n * Assign category IDs to a product.\n */\n async assignProductCategory(\n productId: string,\n categoryIds: string | string[],\n ): Promise<void> {\n const ids = Array.isArray(categoryIds) ? categoryIds : [categoryIds];\n await this.engine.taxonomies.assignTerms(productId, ids);\n }\n\n /**\n * Get assigned categories for a product.\n */\n async getProductCategories(productId: string): Promise<TermItem[]> {\n return this.engine.taxonomies.getContentTerms(\n productId,\n this.categoriesTaxonomy,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Discounts & Coupons\n // ---------------------------------------------------------------------------\n\n /**\n * Create a promotional coupon / discount code.\n */\n async createDiscount(\n input: CreateDiscountInput,\n authorId?: string | null,\n ): Promise<DiscountItem> {\n const normalizedCode = input.code.trim().toUpperCase();\n\n const discountData: DiscountData = {\n code: normalizedCode,\n discountType: input.discountType,\n value: input.value,\n minOrderAmount: input.minOrderAmount,\n maxDiscountAmount: input.maxDiscountAmount,\n maxUses: input.maxUses,\n usedCount: 0,\n startDate: input.startDate,\n endDate: input.endDate,\n status: input.status ?? \"active\",\n appliesToProductIds: input.appliesToProductIds ?? [],\n appliesToCategoryIds: input.appliesToCategoryIds ?? [],\n };\n\n const discount = await this.discountsCollection.create(\n {\n title: input.title,\n slug: normalizedCode.toLowerCase(),\n status: \"published\",\n data: discountData,\n },\n authorId,\n );\n\n await this.engine.hooks.doAction(\"ecommerce.discount_created\", discount);\n return discount;\n }\n\n /**\n * Find a discount code.\n */\n async getDiscountByCode(code: string): Promise<DiscountItem | null> {\n const normalized = code.trim().toUpperCase();\n const result = await this.discountsCollection.find({\n limit: 100,\n });\n\n const match = result.items.find(\n (d) => d.data.code?.toUpperCase() === normalized,\n );\n return match ?? null;\n }\n\n /**\n * Validate a discount coupon against cart items and order subtotal.\n */\n async validateDiscount(\n code: string,\n cartSubtotal: number,\n productIds: string[] = [],\n ): Promise<DiscountValidationResult> {\n const normalized = code.trim().toUpperCase();\n const discount = await this.getDiscountByCode(normalized);\n\n if (!discount) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: `Discount code '${code}' not found.`,\n };\n }\n\n const { data } = discount;\n\n if (data.status !== \"active\") {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: \"Discount code is currently inactive.\",\n };\n }\n\n const now = Date.now();\n if (data.startDate && new Date(data.startDate).getTime() > now) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: \"Discount code is not yet active.\",\n };\n }\n\n if (data.endDate && new Date(data.endDate).getTime() < now) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: \"Discount code has expired.\",\n };\n }\n\n if (data.maxUses !== undefined && data.usedCount >= data.maxUses) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: \"Discount code usage limit reached.\",\n };\n }\n\n if (\n data.minOrderAmount !== undefined &&\n cartSubtotal < data.minOrderAmount\n ) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: `Minimum order amount of ${data.minOrderAmount} required for this coupon.`,\n };\n }\n\n // Check product specific restriction if defined\n if (\n data.appliesToProductIds &&\n data.appliesToProductIds.length > 0 &&\n productIds.length > 0\n ) {\n const hasMatchingProduct = productIds.some((id) =>\n data.appliesToProductIds?.includes(id),\n );\n if (!hasMatchingProduct) {\n return {\n valid: false,\n code: normalized,\n discountAmount: 0,\n message: \"Coupon is not applicable to any products in your cart.\",\n };\n }\n }\n\n // Calculate discount amount\n let discountAmount = 0;\n if (data.discountType === \"percentage\") {\n discountAmount = (cartSubtotal * data.value) / 100;\n if (data.maxDiscountAmount) {\n discountAmount = Math.min(discountAmount, data.maxDiscountAmount);\n }\n } else if (data.discountType === \"fixed_amount\") {\n discountAmount = Math.min(data.value, cartSubtotal);\n } else if (data.discountType === \"free_shipping\") {\n discountAmount = 0; // Handled during shipping calculation\n }\n\n // Apply hook filter for external price overrides\n discountAmount = await this.engine.hooks.applyFilters(\n \"ecommerce.apply_discount\",\n discountAmount,\n { discount, cartSubtotal },\n );\n\n return {\n valid: true,\n code: normalized,\n discountAmount: Math.round(discountAmount * 100) / 100,\n discountType: data.discountType,\n discount,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Cart & Checkout Calculations\n // ---------------------------------------------------------------------------\n\n /**\n * Calculate cart subtotals, apply discounts, shipping, and taxes.\n */\n async calculateCart(\n input: CartCalculationInput,\n ): Promise<CartCalculationResult> {\n const lineItems: OrderLineItem[] = [];\n let subtotal = 0;\n const productIds: string[] = [];\n\n for (const item of input.items) {\n const product = await this.getProduct(item.productId);\n if (!product) {\n throw new Error(\n `[EcommerceService] Product '${item.productId}' not found.`,\n );\n }\n\n productIds.push(product.id);\n\n let price = product.data.price;\n let sku = product.data.sku;\n let title = product.title ?? \"Product\";\n let availableStock = product.data.stock;\n let image = product.data.featuredImage;\n\n if (item.variantId && product.data.variants) {\n const variant = product.data.variants.find(\n (v) => v.id === item.variantId,\n );\n if (variant) {\n price = variant.price ?? price;\n sku = variant.sku ?? sku;\n title = `${title} (${variant.title})`;\n availableStock = variant.stock ?? availableStock;\n image = variant.image ?? image;\n }\n }\n\n // Verify stock availability\n if (\n this.inventoryManagement &&\n product.data.trackInventory &&\n availableStock < item.quantity\n ) {\n throw new Error(\n `[EcommerceService] Insufficient stock for '${title}'. Available: ${availableStock}, Requested: ${item.quantity}.`,\n );\n }\n\n const itemSubtotal = Math.round(price * item.quantity * 100) / 100;\n subtotal += itemSubtotal;\n\n lineItems.push({\n productId: product.id,\n variantId: item.variantId,\n title,\n sku,\n price,\n quantity: item.quantity,\n subtotal: itemSubtotal,\n image,\n });\n }\n\n subtotal = Math.round(subtotal * 100) / 100;\n\n // Apply discount code\n let discountTotal = 0;\n let discountType: string | undefined;\n if (input.discountCode) {\n const validation = await this.validateDiscount(\n input.discountCode,\n subtotal,\n productIds,\n );\n if (validation.valid) {\n discountTotal = validation.discountAmount;\n discountType = validation.discountType;\n }\n }\n\n // Shipping calculation\n let shippingTotal =\n input.shippingCost ?? this.options.defaultShippingCost ?? 0;\n if (discountType === \"free_shipping\") {\n shippingTotal = 0;\n }\n\n // Tax calculation\n const taxRate = input.taxRate ?? this.options.defaultTaxRate ?? 0;\n const taxableAmount = Math.max(0, subtotal - discountTotal);\n const taxTotal = Math.round(taxableAmount * taxRate * 100) / 100;\n\n // Grand total\n const total =\n Math.round((taxableAmount + shippingTotal + taxTotal) * 100) / 100;\n\n const result: CartCalculationResult = {\n items: lineItems,\n subtotal,\n discountTotal,\n discountCode: input.discountCode,\n shippingTotal,\n taxTotal,\n total,\n currency: this.defaultCurrency,\n };\n\n return this.engine.hooks.applyFilters(\n \"ecommerce.calculate_totals\",\n result,\n input,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Orders Management\n // ---------------------------------------------------------------------------\n\n /**\n * Place a new order with cart validation, inventory deduction, and coupon counter updates.\n */\n async createOrder(\n input: CreateOrderInput,\n authorId?: string | null,\n ): Promise<OrderItem> {\n const calc = await this.calculateCart({\n items: input.items,\n discountCode: input.discountCode,\n shippingCost: input.shippingCost,\n taxRate: input.taxRate,\n });\n\n // Generate unique order number: ORD-YYYYMMDD-XXXX\n const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, \"\");\n const randomSuffix = Math.random()\n .toString(36)\n .substring(2, 6)\n .toUpperCase();\n const orderNumber = `ORD-${dateStr}-${randomSuffix}`;\n\n // Decrement stock for purchased items\n if (this.inventoryManagement) {\n for (const item of input.items) {\n await this.adjustStock(item.productId, -item.quantity, item.variantId);\n }\n }\n\n // Increment discount usage counter if applied\n if (input.discountCode) {\n const discount = await this.getDiscountByCode(input.discountCode);\n if (discount) {\n await this.discountsCollection.update(discount.id, {\n data: {\n ...discount.data,\n usedCount: (discount.data.usedCount || 0) + 1,\n },\n });\n }\n }\n\n const orderData: OrderData = {\n orderNumber,\n customerEmail: input.customerEmail,\n customerName: input.customerName,\n status: \"pending\",\n currency: calc.currency,\n items: calc.items,\n subtotal: calc.subtotal,\n discountTotal: calc.discountTotal,\n discountCode: calc.discountCode,\n shippingTotal: calc.shippingTotal,\n taxTotal: calc.taxTotal,\n total: calc.total,\n shippingAddress: input.shippingAddress,\n billingAddress: input.billingAddress,\n paymentMethod: input.paymentMethod,\n notes: input.notes,\n };\n\n const order = await this.ordersCollection.create(\n {\n title: `Order #${orderNumber}`,\n slug: orderNumber.toLowerCase(),\n status: \"published\",\n data: orderData,\n },\n authorId,\n );\n\n await this.engine.hooks.doAction(\"ecommerce.order_created\", order);\n return order;\n }\n\n /**\n * Get order by ID.\n */\n async getOrder(id: string): Promise<OrderItem | null> {\n return this.ordersCollection.findById(id);\n }\n\n /**\n * Get order by order number.\n */\n async getOrderByNumber(orderNumber: string): Promise<OrderItem | null> {\n const result = await this.ordersCollection.find({ limit: 100 });\n const match = result.items.find(\n (o) => o.data.orderNumber?.toUpperCase() === orderNumber.toUpperCase(),\n );\n return match ?? null;\n }\n\n /**\n * Update the status of an order (e.g. pending -> paid -> shipped).\n */\n async updateOrderStatus(\n id: string,\n status: OrderStatus,\n note?: string,\n ): Promise<OrderItem | null> {\n const existing = await this.getOrder(id);\n if (!existing) return null;\n\n const oldStatus = existing.data.status;\n const updated = await this.ordersCollection.update(\n id,\n {\n data: {\n ...existing.data,\n status,\n },\n },\n undefined,\n note,\n );\n\n if (updated) {\n await this.engine.hooks.doAction(\"ecommerce.order_status_changed\", {\n order: updated,\n oldStatus,\n newStatus: status,\n note,\n });\n }\n\n return updated;\n }\n}\n","/**\n * @azlib/cms - Built-in E-commerce Web Standard HTTP API Routes\n */\n\nimport type { CMSPluginContext } from \"../../core/plugin.js\";\nimport type { EcommerceService } from \"./service.js\";\nimport type {\n CartCalculationInput,\n CreateDiscountInput,\n CreateOrderInput,\n CreateProductInput,\n EcommercePluginOptions,\n OrderStatus,\n UpdateProductInput,\n} from \"./types.js\";\n\nfunction json(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Access-Control-Allow-Origin\": \"*\",\n },\n });\n}\n\nfunction badRequest(message: string): Response {\n return json({ error: message }, 400);\n}\n\nfunction notFound(message: string): Response {\n return json({ error: message }, 404);\n}\n\nexport function registerEcommerceRoutes(\n ctx: CMSPluginContext,\n service: EcommerceService,\n options: EcommercePluginOptions = {},\n): void {\n const prefix = (options.apiPrefix ?? \"/api/ecommerce\").replace(/\\/+$/, \"\");\n\n // ---------------------------------------------------------------------------\n // Products Endpoints\n // ---------------------------------------------------------------------------\n\n // GET /api/ecommerce/products\n ctx.registerRoute(\"GET\", `${prefix}/products`, async (_req, { url }) => {\n try {\n const categorySlug = url.searchParams.get(\"category\") ?? undefined;\n const categoryId = url.searchParams.get(\"categoryId\") ?? undefined;\n const tagSlug = url.searchParams.get(\"tag\") ?? undefined;\n const brandSlug = url.searchParams.get(\"brand\") ?? undefined;\n const search = url.searchParams.get(\"search\") ?? undefined;\n const statusParam = url.searchParams.get(\"status\") as any;\n const inStock = url.searchParams.get(\"inStock\") === \"true\";\n\n const minPriceStr = url.searchParams.get(\"minPrice\");\n const maxPriceStr = url.searchParams.get(\"maxPrice\");\n const minPrice = minPriceStr ? parseFloat(minPriceStr) : undefined;\n const maxPrice = maxPriceStr ? parseFloat(maxPriceStr) : undefined;\n\n const orderBy = url.searchParams.get(\"orderBy\") as any;\n const orderDirection = (url.searchParams.get(\"orderDirection\") ??\n \"desc\") as \"asc\" | \"desc\";\n\n const limitStr = url.searchParams.get(\"limit\");\n const offsetStr = url.searchParams.get(\"offset\");\n const limit = limitStr ? parseInt(limitStr, 10) : 20;\n const offset = offsetStr ? parseInt(offsetStr, 10) : 0;\n\n const results = await service.listProducts({\n categorySlug,\n categoryId,\n tagSlug,\n brandSlug,\n search,\n status: statusParam,\n inStock,\n minPrice,\n maxPrice,\n orderBy,\n orderDirection,\n limit,\n offset,\n });\n\n return json(results);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // GET /api/ecommerce/products/:id\n ctx.registerRoute(\n \"GET\",\n `${prefix}/products/:id`,\n async (_req, { params, url }) => {\n const id = params.id;\n const by = url.searchParams.get(\"by\");\n\n let product = null;\n if (by === \"slug\") {\n product = await service.getProductBySlug(id);\n } else {\n product = await service.getProduct(id);\n if (!product) {\n product = await service.getProductBySlug(id);\n }\n }\n\n if (!product) {\n return notFound(`Product '${id}' not found`);\n }\n\n return json(product);\n },\n );\n\n // POST /api/ecommerce/products\n ctx.registerRoute(\"POST\", `${prefix}/products`, async (req) => {\n try {\n const body = (await req.json()) as CreateProductInput;\n if (!body.title) {\n return badRequest(\"Product 'title' is required.\");\n }\n if (body.price === undefined || body.price < 0) {\n return badRequest(\"Valid product 'price' is required.\");\n }\n\n const product = await service.createProduct(body);\n return json(product, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // PUT /api/ecommerce/products/:id\n ctx.registerRoute(\n \"PUT\",\n `${prefix}/products/:id`,\n async (req, { params }) => {\n try {\n const body = (await req.json()) as UpdateProductInput;\n const updated = await service.updateProduct(params.id, body);\n if (!updated) {\n return notFound(`Product '${params.id}' not found.`);\n }\n return json(updated);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // DELETE /api/ecommerce/products/:id\n ctx.registerRoute(\n \"DELETE\",\n `${prefix}/products/:id`,\n async (_req, { params }) => {\n const deleted = await service.deleteProduct(params.id);\n if (!deleted) {\n return notFound(`Product '${params.id}' not found.`);\n }\n return json({ success: true, id: params.id });\n },\n );\n\n // POST /api/ecommerce/products/:id/images\n ctx.registerRoute(\n \"POST\",\n `${prefix}/products/:id/images`,\n async (req, { params }) => {\n try {\n const body = await req.json();\n if (!body.filename || !body.mimeType) {\n return badRequest(\"'filename' and 'mimeType' are required.\");\n }\n\n const result = await service.uploadProductImage(params.id, {\n filename: body.filename,\n mimeType: body.mimeType,\n sizeBytes: body.sizeBytes ?? 0,\n url: body.url,\n altText: body.altText,\n caption: body.caption,\n width: body.width,\n height: body.height,\n isFeatured: body.isFeatured,\n });\n\n return json(result, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // ---------------------------------------------------------------------------\n // Categories & Catalog Endpoints\n // ---------------------------------------------------------------------------\n\n // GET /api/ecommerce/categories\n ctx.registerRoute(\"GET\", `${prefix}/categories`, async (_req, { url }) => {\n try {\n const isTree = url.searchParams.get(\"tree\") === \"true\";\n if (isTree) {\n const tree = await service.getCategoryTree();\n return json(tree);\n }\n const parentId = url.searchParams.get(\"parentId\");\n const list = await service.getCategories({\n parentId: parentId === \"null\" ? null : (parentId ?? undefined),\n });\n return json(list);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // POST /api/ecommerce/categories\n ctx.registerRoute(\"POST\", `${prefix}/categories`, async (req) => {\n try {\n const body = await req.json();\n if (!body.name) {\n return badRequest(\"Category 'name' is required.\");\n }\n const category = await service.createCategory(body);\n return json(category, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // ---------------------------------------------------------------------------\n // Discounts & Coupons Endpoints\n // ---------------------------------------------------------------------------\n\n if (options.enableDiscounts !== false) {\n // POST /api/ecommerce/discounts\n ctx.registerRoute(\"POST\", `${prefix}/discounts`, async (req) => {\n try {\n const body = (await req.json()) as CreateDiscountInput;\n if (!body.title || !body.code) {\n return badRequest(\"'title' and 'code' are required.\");\n }\n if (body.value === undefined || body.value < 0) {\n return badRequest(\"Valid discount 'value' is required.\");\n }\n const discount = await service.createDiscount(body);\n return json(discount, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // POST /api/ecommerce/discounts/validate\n ctx.registerRoute(\"POST\", `${prefix}/discounts/validate`, async (req) => {\n try {\n const body = await req.json();\n if (!body.code) {\n return badRequest(\"Discount 'code' is required.\");\n }\n const subtotal = Number(body.subtotal ?? 0);\n const productIds = Array.isArray(body.productIds)\n ? body.productIds\n : [];\n\n const result = await service.validateDiscount(\n body.code,\n subtotal,\n productIds,\n );\n return json(result);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n }\n\n // ---------------------------------------------------------------------------\n // Cart & Order Endpoints\n // ---------------------------------------------------------------------------\n\n // POST /api/ecommerce/cart/calculate\n ctx.registerRoute(\"POST\", `${prefix}/cart/calculate`, async (req) => {\n try {\n const body = (await req.json()) as CartCalculationInput;\n if (\n !body.items ||\n !Array.isArray(body.items) ||\n body.items.length === 0\n ) {\n return badRequest(\"'items' array is required and must not be empty.\");\n }\n const calculation = await service.calculateCart(body);\n return json(calculation);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n if (options.enableOrders !== false) {\n // POST /api/ecommerce/orders\n ctx.registerRoute(\"POST\", `${prefix}/orders`, async (req) => {\n try {\n const body = (await req.json()) as CreateOrderInput;\n if (!body.customerEmail) {\n return badRequest(\"'customerEmail' is required.\");\n }\n if (\n !body.items ||\n !Array.isArray(body.items) ||\n body.items.length === 0\n ) {\n return badRequest(\"'items' array is required.\");\n }\n\n const order = await service.createOrder(body);\n return json(order, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // GET /api/ecommerce/orders/:id\n ctx.registerRoute(\n \"GET\",\n `${prefix}/orders/:id`,\n async (_req, { params, url }) => {\n const id = params.id;\n const by = url.searchParams.get(\"by\");\n\n let order = null;\n if (by === \"number\") {\n order = await service.getOrderByNumber(id);\n } else {\n order = await service.getOrder(id);\n if (!order) {\n order = await service.getOrderByNumber(id);\n }\n }\n\n if (!order) {\n return notFound(`Order '${id}' not found.`);\n }\n\n return json(order);\n },\n );\n\n // PATCH /api/ecommerce/orders/:id/status\n ctx.registerRoute(\n \"PATCH\",\n `${prefix}/orders/:id/status`,\n async (req, { params }) => {\n try {\n const body = await req.json();\n if (!body.status) {\n return badRequest(\"New 'status' is required.\");\n }\n const updated = await service.updateOrderStatus(\n params.id,\n body.status as OrderStatus,\n body.note,\n );\n if (!updated) {\n return notFound(`Order '${params.id}' not found.`);\n }\n return json(updated);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n }\n}\n","/**\n * @azlib/cms - Built-in E-commerce Headless Client Extension\n */\n\nimport type { CMSClient } from \"../../client/cms-client.js\";\nimport type {\n MediaItem,\n PaginatedResult,\n TermItem,\n TermTreeItem,\n} from \"../../core/types.js\";\nimport { EcommerceService } from \"./service.js\";\nimport type {\n CartCalculationInput,\n CartCalculationResult,\n CreateDiscountInput,\n CreateOrderInput,\n CreateProductInput,\n DiscountItem,\n DiscountValidationResult,\n EcommercePluginOptions,\n EcommerceProductQuery,\n OrderItem,\n OrderStatus,\n ProductItem,\n UpdateProductInput,\n} from \"./types.js\";\n\nexport class EcommerceClient {\n private service?: EcommerceService;\n private prefix: string;\n\n constructor(\n private client: CMSClient,\n private options: EcommercePluginOptions = {},\n ) {\n this.prefix = (options.apiPrefix ?? \"/api/ecommerce\").replace(/\\/+$/, \"\");\n const engine = client.getEngine();\n if (engine) {\n this.service = new EcommerceService(engine, options);\n }\n }\n\n readonly products = {\n find: async (\n query: EcommerceProductQuery = {},\n ): Promise<PaginatedResult<ProductItem>> => {\n if (this.service) {\n return this.service.listProducts(query);\n }\n const params = new URLSearchParams();\n if (query.categorySlug) params.set(\"category\", query.categorySlug);\n if (query.categoryId) params.set(\"categoryId\", query.categoryId);\n if (query.tagSlug) params.set(\"tag\", query.tagSlug);\n if (query.brandSlug) params.set(\"brand\", query.brandSlug);\n if (query.search) params.set(\"search\", query.search);\n if (query.inStock) params.set(\"inStock\", \"true\");\n if (query.minPrice !== undefined)\n params.set(\"minPrice\", String(query.minPrice));\n if (query.maxPrice !== undefined)\n params.set(\"maxPrice\", String(query.maxPrice));\n if (query.orderBy) params.set(\"orderBy\", query.orderBy);\n if (query.orderDirection)\n params.set(\"orderDirection\", query.orderDirection);\n if (query.limit !== undefined) params.set(\"limit\", String(query.limit));\n if (query.offset !== undefined)\n params.set(\"offset\", String(query.offset));\n\n const q = params.toString() ? `?${params.toString()}` : \"\";\n return this.client.request<PaginatedResult<ProductItem>>(\n `${this.prefix}/products${q}`,\n );\n },\n\n get: async (\n idOrSlug: string,\n by?: \"id\" | \"slug\",\n ): Promise<ProductItem | null> => {\n if (this.service) {\n return by === \"slug\"\n ? this.service.getProductBySlug(idOrSlug)\n : this.service.getProduct(idOrSlug);\n }\n const query = by ? `?by=${by}` : \"\";\n return this.client.request<ProductItem | null>(\n `${this.prefix}/products/${encodeURIComponent(idOrSlug)}${query}`,\n );\n },\n\n create: async (data: CreateProductInput): Promise<ProductItem> => {\n if (this.service) {\n return this.service.createProduct(data);\n }\n return this.client.request<ProductItem>(`${this.prefix}/products`, {\n method: \"POST\",\n body: JSON.stringify(data),\n });\n },\n\n update: async (\n id: string,\n data: UpdateProductInput,\n ): Promise<ProductItem | null> => {\n if (this.service) {\n return this.service.updateProduct(id, data);\n }\n return this.client.request<ProductItem | null>(\n `${this.prefix}/products/${encodeURIComponent(id)}`,\n {\n method: \"PUT\",\n body: JSON.stringify(data),\n },\n );\n },\n\n delete: async (id: string): Promise<boolean> => {\n if (this.service) {\n return this.service.deleteProduct(id);\n }\n const res = await this.client.request<{ success: boolean }>(\n `${this.prefix}/products/${encodeURIComponent(id)}`,\n {\n method: \"DELETE\",\n },\n );\n return Boolean(res?.success);\n },\n\n uploadImage: async (\n productId: string,\n file: {\n filename: string;\n mimeType: string;\n sizeBytes: number;\n url?: string;\n altText?: string;\n caption?: string;\n width?: number;\n height?: number;\n isFeatured?: boolean;\n },\n ): Promise<{ media: MediaItem; product: ProductItem }> => {\n if (this.service) {\n return this.service.uploadProductImage(productId, file);\n }\n return this.client.request<{ media: MediaItem; product: ProductItem }>(\n `${this.prefix}/products/${encodeURIComponent(productId)}/images`,\n {\n method: \"POST\",\n body: JSON.stringify(file),\n },\n );\n },\n };\n\n readonly categories = {\n list: async (options?: {\n parentId?: string | null;\n }): Promise<TermItem[]> => {\n if (this.service) {\n return this.service.getCategories(options);\n }\n const q =\n options?.parentId !== undefined ? `?parentId=${options.parentId}` : \"\";\n return this.client.request<TermItem[]>(`${this.prefix}/categories${q}`);\n },\n\n tree: async (): Promise<TermTreeItem[]> => {\n if (this.service) {\n return this.service.getCategoryTree();\n }\n return this.client.request<TermTreeItem[]>(\n `${this.prefix}/categories?tree=true`,\n );\n },\n\n create: async (input: {\n name: string;\n slug?: string;\n parentId?: string | null;\n description?: string;\n }): Promise<TermItem> => {\n if (this.service) {\n return this.service.createCategory(input);\n }\n return this.client.request<TermItem>(`${this.prefix}/categories`, {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n },\n };\n\n readonly discounts = {\n validate: async (\n code: string,\n subtotal: number,\n productIds?: string[],\n ): Promise<DiscountValidationResult> => {\n if (this.service) {\n return this.service.validateDiscount(code, subtotal, productIds);\n }\n return this.client.request<DiscountValidationResult>(\n `${this.prefix}/discounts/validate`,\n {\n method: \"POST\",\n body: JSON.stringify({ code, subtotal, productIds }),\n },\n );\n },\n\n create: async (input: CreateDiscountInput): Promise<DiscountItem> => {\n if (this.service) {\n return this.service.createDiscount(input);\n }\n return this.client.request<DiscountItem>(`${this.prefix}/discounts`, {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n },\n };\n\n readonly cart = {\n calculate: async (\n input: CartCalculationInput,\n ): Promise<CartCalculationResult> => {\n if (this.service) {\n return this.service.calculateCart(input);\n }\n return this.client.request<CartCalculationResult>(\n `${this.prefix}/cart/calculate`,\n {\n method: \"POST\",\n body: JSON.stringify(input),\n },\n );\n },\n };\n\n readonly orders = {\n create: async (input: CreateOrderInput): Promise<OrderItem> => {\n if (this.service) {\n return this.service.createOrder(input);\n }\n return this.client.request<OrderItem>(`${this.prefix}/orders`, {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n },\n\n get: async (\n idOrNumber: string,\n by?: \"id\" | \"number\",\n ): Promise<OrderItem | null> => {\n if (this.service) {\n return by === \"number\"\n ? this.service.getOrderByNumber(idOrNumber)\n : this.service.getOrder(idOrNumber);\n }\n const q = by ? `?by=${by}` : \"\";\n return this.client.request<OrderItem | null>(\n `${this.prefix}/orders/${encodeURIComponent(idOrNumber)}${q}`,\n );\n },\n\n updateStatus: async (\n id: string,\n status: OrderStatus,\n note?: string,\n ): Promise<OrderItem | null> => {\n if (this.service) {\n return this.service.updateOrderStatus(id, status, note);\n }\n return this.client.request<OrderItem | null>(\n `${this.prefix}/orders/${encodeURIComponent(id)}/status`,\n {\n method: \"PATCH\",\n body: JSON.stringify({ status, note }),\n },\n );\n },\n };\n}\n\n/**\n * Get or create an EcommerceClient adapter for a CMSClient.\n */\nexport function getEcommerceClient(\n client: CMSClient,\n options?: EcommercePluginOptions,\n): EcommerceClient {\n return new EcommerceClient(client, options);\n}\n","/**\n * @azlib/cms - Built-in E-commerce Plugin\n */\n\nimport { definePlugin, type CMSPlugin } from \"../../core/plugin.js\";\nimport type { CMSEngine } from \"../../core/engine.js\";\nimport {\n createDiscountCollection,\n createEcommerceTaxonomies,\n createOrderCollection,\n createProductCollection,\n} from \"./schemas.js\";\nimport { EcommerceService } from \"./service.js\";\nimport { registerEcommerceRoutes } from \"./routes.js\";\nimport type { EcommercePluginOptions } from \"./types.js\";\n\nexport * from \"./types.js\";\nexport * from \"./schemas.js\";\nexport * from \"./service.js\";\nexport * from \"./client.js\";\n\n/**\n * Built-in E-commerce plugin factory for @azlib/cms.\n * Equips the CMS engine with product catalogs, hierarchical categories,\n * image uploading, discount coupons, cart calculation, and order tracking.\n */\nexport const ecommercePlugin = definePlugin<EcommercePluginOptions | void>(\n (options: EcommercePluginOptions | void): CMSPlugin => {\n const opts: EcommercePluginOptions = options || {};\n const collections = [createProductCollection(opts)];\n\n if (opts.enableDiscounts !== false) {\n collections.push(createDiscountCollection(opts));\n }\n\n if (opts.enableOrders !== false) {\n collections.push(createOrderCollection(opts));\n }\n\n const taxonomies = createEcommerceTaxonomies(opts);\n\n return {\n name: \"ecommerce\",\n version: \"1.0.0\",\n description:\n \"Built-in E-commerce shopping, products, catalogs, discounts, and orders plugin\",\n collections,\n taxonomies,\n\n setup(ctx) {\n const service = new EcommerceService(ctx.engine, opts);\n // Cache instance on engine for retrieval via getEcommerceService\n (ctx.engine as any).__ecommerceService = service;\n registerEcommerceRoutes(ctx, service, opts);\n },\n };\n },\n);\n\n/**\n * Retrieve the active EcommerceService instance associated with a CMSEngine.\n */\nexport function getEcommerceService(\n engine: CMSEngine,\n options?: EcommercePluginOptions,\n): EcommerceService {\n if ((engine as any).__ecommerceService) {\n return (engine as any).__ecommerceService;\n }\n const service = new EcommerceService(engine, options);\n (engine as any).__ecommerceService = service;\n return service;\n}\n","/**\n * @azlib/cms - Built-in HRMS Declarative Content Schemas & Taxonomies\n */\n\nimport type { CollectionConfig, TaxonomyConfig } from \"../../core/types.js\";\nimport { collection, fields } from \"../../content/schema.js\";\nimport type { HRMSPluginOptions } from \"./types.js\";\n\n/**\n * Creates the collection configuration for Employers (Organizations / Companies).\n */\nexport function createEmployerCollection(\n options: HRMSPluginOptions = {},\n): CollectionConfig {\n const slug = options.employerCollectionSlug ?? \"employers\";\n\n return collection({\n slug,\n label: \"Employers\",\n singularLabel: \"Employer\",\n description:\n \"Companies and organizational entities managing employees, shifts, and leave policies\",\n timestamps: true,\n revisions: true,\n draftable: true,\n defaultSort: {\n field: \"createdAt\",\n direction: \"desc\",\n },\n fields: [\n fields.text({\n name: \"companyName\",\n label: \"Company Name\",\n required: true,\n }),\n fields.slug({\n from: \"companyName\",\n unique: true,\n }),\n fields.text({\n name: \"legalName\",\n label: \"Legal Entity Name\",\n }),\n fields.text({\n name: \"taxId\",\n label: \"Tax / EIN Number\",\n }),\n fields.text({\n name: \"email\",\n label: \"Primary Email\",\n }),\n fields.text({\n name: \"phone\",\n label: \"Phone Number\",\n }),\n fields.text({\n name: \"website\",\n label: \"Website URL\",\n }),\n fields.image({\n name: \"logo\",\n label: \"Company Logo\",\n }),\n fields.json({\n name: \"address\",\n label: \"Company Address\",\n }),\n fields.text({\n name: \"timezone\",\n label: \"Primary Timezone\",\n defaultValue: \"UTC\",\n }),\n fields.json({\n name: \"workSchedule\",\n label: \"Standard Work Schedule\",\n defaultValue: {\n startTime: options.workScheduleStart ?? \"09:00\",\n endTime: options.workScheduleEnd ?? \"17:00\",\n standardHoursPerDay: options.standardWorkDayHours ?? 8,\n gracePeriodMinutes: options.gracePeriodMinutes ?? 15,\n workDays: [1, 2, 3, 4, 5],\n },\n }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"active\", \"inactive\"],\n defaultValue: \"active\",\n }),\n ],\n });\n}\n\n/**\n * Creates the collection configuration for Employees.\n */\nexport function createEmployeeCollection(\n options: HRMSPluginOptions = {},\n): CollectionConfig {\n const slug = options.employeeCollectionSlug ?? \"employees\";\n const employerSlug = options.employerCollectionSlug ?? \"employers\";\n const deptSlug = options.departmentsTaxonomySlug ?? \"hrms_departments\";\n const desigSlug = options.designationsTaxonomySlug ?? \"hrms_designations\";\n\n return collection({\n slug,\n label: \"Employees\",\n singularLabel: \"Employee\",\n description:\n \"Employee profiles, job assignments, emergency contacts, and attached records\",\n timestamps: true,\n revisions: true,\n draftable: true,\n taxonomies: [deptSlug, desigSlug],\n defaultSort: {\n field: \"createdAt\",\n direction: \"desc\",\n },\n fields: [\n fields.relationship({\n name: \"employerId\",\n label: \"Employer\",\n targetCollection: employerSlug,\n required: true,\n }),\n fields.text({\n name: \"userId\",\n label: \"Associated User ID\",\n description: \"Optional reference to an authenticated user account\",\n }),\n fields.text({\n name: \"employeeNumber\",\n label: \"Employee Number\",\n required: true,\n unique: true,\n }),\n fields.text({\n name: \"firstName\",\n label: \"First Name\",\n required: true,\n }),\n fields.text({\n name: \"lastName\",\n label: \"Last Name\",\n required: true,\n }),\n fields.text({\n name: \"email\",\n label: \"Work Email\",\n required: true,\n }),\n fields.text({\n name: \"phone\",\n label: \"Contact Phone\",\n }),\n fields.image({\n name: \"avatar\",\n label: \"Profile Picture\",\n }),\n fields.text({\n name: \"jobTitle\",\n label: \"Job Title\",\n }),\n fields.select({\n name: \"employmentType\",\n label: \"Employment Type\",\n options: [\"full_time\", \"part_time\", \"contractor\", \"intern\"],\n defaultValue: \"full_time\",\n }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"active\", \"on_leave\", \"terminated\", \"suspended\"],\n defaultValue: \"active\",\n }),\n fields.date({\n name: \"hireDate\",\n label: \"Hire Date\",\n required: true,\n }),\n fields.date({\n name: \"terminationDate\",\n label: \"Termination Date\",\n }),\n fields.relationship({\n name: \"managerId\",\n label: \"Reporting Manager\",\n targetCollection: slug,\n }),\n fields.json({\n name: \"emergencyContact\",\n label: \"Emergency Contact\",\n }),\n fields.repeater({\n name: \"documents\",\n label: \"Attached Documents & Contracts\",\n fields: [\n fields.text({\n name: \"title\",\n label: \"Document Title\",\n required: true,\n }),\n fields.text({ name: \"fileUrl\", label: \"File URL\", required: true }),\n fields.text({ name: \"category\", label: \"Category\" }),\n fields.text({ name: \"uploadedAt\", label: \"Uploaded Date\" }),\n ],\n }),\n fields.number({\n name: \"salary\",\n label: \"Base Salary\",\n }),\n fields.text({\n name: \"notes\",\n label: \"Internal Notes\",\n }),\n ],\n });\n}\n\n/**\n * Creates the collection configuration for Daily Attendance.\n */\nexport function createAttendanceCollection(\n options: HRMSPluginOptions = {},\n): CollectionConfig {\n const slug = options.attendanceCollectionSlug ?? \"attendance\";\n const employerSlug = options.employerCollectionSlug ?? \"employers\";\n const employeeSlug = options.employeeCollectionSlug ?? \"employees\";\n\n return collection({\n slug,\n label: \"Attendance\",\n singularLabel: \"Attendance Record\",\n description:\n \"Daily check-in and check-out logs, hours worked, overtime, and punctuality status\",\n timestamps: true,\n revisions: false,\n draftable: false,\n defaultSort: {\n field: \"date\",\n direction: \"desc\",\n },\n fields: [\n fields.relationship({\n name: \"employerId\",\n label: \"Employer\",\n targetCollection: employerSlug,\n required: true,\n }),\n fields.relationship({\n name: \"employeeId\",\n label: \"Employee\",\n targetCollection: employeeSlug,\n required: true,\n }),\n fields.date({\n name: \"date\",\n label: \"Date\",\n required: true,\n }),\n fields.text({\n name: \"checkInAt\",\n label: \"Check-In Timestamp\",\n required: true,\n }),\n fields.text({\n name: \"checkOutAt\",\n label: \"Check-Out Timestamp\",\n }),\n fields.number({\n name: \"totalHours\",\n label: \"Total Hours\",\n defaultValue: 0,\n }),\n fields.number({\n name: \"overtimeHours\",\n label: \"Overtime Hours\",\n defaultValue: 0,\n }),\n fields.select({\n name: \"status\",\n label: \"Status\",\n options: [\"present\", \"late\", \"half_day\", \"absent\", \"on_leave\"],\n defaultValue: \"present\",\n }),\n fields.text({\n name: \"location\",\n label: \"Location / IP / Geofence\",\n }),\n fields.text({\n name: \"notes\",\n label: \"Notes\",\n }),\n ],\n });\n}\n\n/**\n * Creates the collection configuration for Leave Types.\n */\nexport function createLeaveTypeCollection(\n options: HRMSPluginOptions = {},\n): CollectionConfig {\n const slug = options.leaveTypeCollectionSlug ?? \"leave_types\";\n const employerSlug = options.employerCollectionSlug ?? \"employers\";\n\n return collection({\n slug,\n label: \"Leave Types\",\n singularLabel: \"Leave Type\",\n description:\n \"Available leave categories (Annual, Sick, Unpaid) and yearly quotas\",\n timestamps: true,\n revisions: true,\n draftable: false,\n fields: [\n fields.relationship({\n name: \"employerId\",\n label: \"Employer\",\n targetCollection: employerSlug,\n }),\n fields.text({\n name: \"name\",\n label: \"Leave Name\",\n required: true,\n }),\n fields.text({\n name: \"code\",\n label: \"Leave Code\",\n required: true,\n }),\n fields.number({\n name: \"daysAllowedPerYear\",\n label: \"Days Allowed Per Year\",\n required: true,\n defaultValue: 15,\n min: 0,\n }),\n fields.boolean({\n name: \"paid\",\n label: \"Paid Leave\",\n defaultValue: true,\n }),\n fields.boolean({\n name: \"requiresApproval\",\n label: \"Requires Manager Approval\",\n defaultValue: true,\n }),\n fields.text({\n name: \"color\",\n label: \"Display Color Code\",\n }),\n fields.text({\n name: \"description\",\n label: \"Description / Policy\",\n }),\n ],\n });\n}\n\n/**\n * Creates the collection configuration for Leave Requests.\n */\nexport function createLeaveRequestCollection(\n options: HRMSPluginOptions = {},\n): CollectionConfig {\n const slug = options.leaveRequestCollectionSlug ?? \"leave_requests\";\n const employerSlug = options.employerCollectionSlug ?? \"employers\";\n const employeeSlug = options.employeeCollectionSlug ?? \"employees\";\n const leaveTypeSlug = options.leaveTypeCollectionSlug ?? \"leave_types\";\n\n return collection({\n slug,\n label: \"Leave Requests\",\n singularLabel: \"Leave Request\",\n description:\n \"Employee time-off requests, approval tracking, and deducted balances\",\n timestamps: true,\n revisions: true,\n draftable: false,\n defaultSort: {\n field: \"createdAt\",\n direction: \"desc\",\n },\n fields: [\n fields.relationship({\n name: \"employerId\",\n label: \"Employer\",\n targetCollection: employerSlug,\n required: true,\n }),\n fields.relationship({\n name: \"employeeId\",\n label: \"Employee\",\n targetCollection: employeeSlug,\n required: true,\n }),\n fields.relationship({\n name: \"leaveTypeId\",\n label: \"Leave Type\",\n targetCollection: leaveTypeSlug,\n required: true,\n }),\n fields.date({\n name: \"startDate\",\n label: \"Start Date\",\n required: true,\n }),\n fields.date({\n name: \"endDate\",\n label: \"End Date\",\n required: true,\n }),\n fields.number({\n name: \"daysCount\",\n label: \"Days Count\",\n required: true,\n min: 0.5,\n }),\n fields.text({\n name: \"reason\",\n label: \"Reason\",\n }),\n fields.select({\n name: \"status\",\n label: \"Request Status\",\n options: [\"pending\", \"approved\", \"rejected\", \"cancelled\"],\n defaultValue: \"pending\",\n }),\n fields.relationship({\n name: \"approvedBy\",\n label: \"Approved / Rejected By\",\n targetCollection: employeeSlug,\n }),\n fields.text({\n name: \"approvedAt\",\n label: \"Decision Timestamp\",\n }),\n fields.text({\n name: \"rejectionReason\",\n label: \"Rejection Reason\",\n }),\n ],\n });\n}\n\n/**\n * Creates the standard HRMS taxonomies: departments and designations.\n */\nexport function createHRMSTaxonomies(\n options: HRMSPluginOptions = {},\n): TaxonomyConfig[] {\n const employeeSlug = options.employeeCollectionSlug ?? \"employees\";\n const deptSlug = options.departmentsTaxonomySlug ?? \"hrms_departments\";\n const desigSlug = options.designationsTaxonomySlug ?? \"hrms_designations\";\n\n return [\n {\n slug: deptSlug,\n label: \"Departments\",\n singularLabel: \"Department\",\n hierarchical: true,\n postTypes: [employeeSlug],\n description:\n \"Hierarchical departmental tree (e.g. Engineering, Sales, HR)\",\n },\n {\n slug: desigSlug,\n label: \"Designations\",\n singularLabel: \"Designation\",\n hierarchical: false,\n postTypes: [employeeSlug],\n description: \"Job titles and designations across the workforce\",\n },\n ];\n}\n","/**\n * @azlib/cms - Built-in HRMS Service Engine\n */\n\nimport type { CMSEngine, CollectionService } from \"../../core/engine.js\";\nimport type { PaginatedResult } from \"../../core/types.js\";\nimport type {\n ApproveLeaveInput,\n AttendanceData,\n AttendanceItem,\n AttendanceStatus,\n CheckInInput,\n CheckOutInput,\n CreateEmployeeInput,\n CreateEmployerInput,\n CreateLeaveRequestInput,\n CreateLeaveTypeInput,\n EmployeeData,\n EmployeeItem,\n EmployeeLeaveBalanceReport,\n EmployerData,\n EmployerItem,\n HRMSAttendanceQuery,\n HRMSEmployeeQuery,\n HRMSLeaveQuery,\n HRMSPluginOptions,\n LeaveBalanceItem,\n LeaveRequestData,\n LeaveRequestItem,\n LeaveTypeData,\n LeaveTypeItem,\n RecordAttendanceManualInput,\n RejectLeaveInput,\n UpdateEmployeeInput,\n UpdateEmployerInput,\n} from \"./types.js\";\n\nexport class HRMSService {\n readonly employerSlug: string;\n readonly employeeSlug: string;\n readonly attendanceSlug: string;\n readonly leaveTypeSlug: string;\n readonly leaveRequestSlug: string;\n readonly departmentsTaxonomy: string;\n readonly designationsTaxonomy: string;\n readonly standardWorkDayHours: number;\n readonly workScheduleStart: string;\n readonly workScheduleEnd: string;\n readonly gracePeriodMinutes: number;\n\n constructor(\n readonly engine: CMSEngine,\n readonly options: HRMSPluginOptions = {},\n ) {\n this.employerSlug = options.employerCollectionSlug ?? \"employers\";\n this.employeeSlug = options.employeeCollectionSlug ?? \"employees\";\n this.attendanceSlug = options.attendanceCollectionSlug ?? \"attendance\";\n this.leaveTypeSlug = options.leaveTypeCollectionSlug ?? \"leave_types\";\n this.leaveRequestSlug =\n options.leaveRequestCollectionSlug ?? \"leave_requests\";\n this.departmentsTaxonomy =\n options.departmentsTaxonomySlug ?? \"hrms_departments\";\n this.designationsTaxonomy =\n options.designationsTaxonomySlug ?? \"hrms_designations\";\n this.standardWorkDayHours = options.standardWorkDayHours ?? 8;\n this.workScheduleStart = options.workScheduleStart ?? \"09:00\";\n this.workScheduleEnd = options.workScheduleEnd ?? \"17:00\";\n this.gracePeriodMinutes = options.gracePeriodMinutes ?? 15;\n }\n\n // ---------------------------------------------------------------------------\n // Collections Getters\n // ---------------------------------------------------------------------------\n\n private get employersCollection(): CollectionService<EmployerData> {\n return this.engine.collection<EmployerData>(this.employerSlug);\n }\n\n private get employeesCollection(): CollectionService<EmployeeData> {\n return this.engine.collection<EmployeeData>(this.employeeSlug);\n }\n\n private get attendanceCollection(): CollectionService<AttendanceData> {\n return this.engine.collection<AttendanceData>(this.attendanceSlug);\n }\n\n private get leaveTypesCollection(): CollectionService<LeaveTypeData> {\n return this.engine.collection<LeaveTypeData>(this.leaveTypeSlug);\n }\n\n private get leaveRequestsCollection(): CollectionService<LeaveRequestData> {\n return this.engine.collection<LeaveRequestData>(this.leaveRequestSlug);\n }\n\n // ---------------------------------------------------------------------------\n // Employer Management\n // ---------------------------------------------------------------------------\n\n async createEmployer(\n input: CreateEmployerInput,\n authorId?: string | null,\n ): Promise<EmployerItem> {\n const employerData: EmployerData = {\n companyName: input.companyName,\n legalName: input.legalName,\n taxId: input.taxId,\n email: input.email,\n phone: input.phone,\n website: input.website,\n logo: input.logo,\n address: input.address,\n timezone: input.timezone ?? \"UTC\",\n workSchedule: input.workSchedule ?? {\n startTime: this.workScheduleStart,\n endTime: this.workScheduleEnd,\n standardHoursPerDay: this.standardWorkDayHours,\n gracePeriodMinutes: this.gracePeriodMinutes,\n workDays: [1, 2, 3, 4, 5],\n },\n status: input.status ?? \"active\",\n };\n\n const employer = await this.employersCollection.create(\n {\n title: input.companyName,\n status: input.status === \"inactive\" ? \"draft\" : \"published\",\n data: employerData,\n },\n authorId,\n );\n\n await this.engine.hooks.doAction(\"hrms.employer_created\", employer);\n return employer;\n }\n\n async getEmployer(id: string): Promise<EmployerItem | null> {\n return this.employersCollection.findById(id);\n }\n\n async getEmployerBySlug(slug: string): Promise<EmployerItem | null> {\n return this.employersCollection.findBySlug(slug);\n }\n\n async updateEmployer(\n id: string,\n input: UpdateEmployerInput,\n authorId?: string | null,\n ): Promise<EmployerItem | null> {\n const existing = await this.getEmployer(id);\n if (!existing) return null;\n\n const updatedData: EmployerData = {\n ...existing.data,\n ...(input.companyName !== undefined\n ? { companyName: input.companyName }\n : {}),\n ...(input.legalName !== undefined ? { legalName: input.legalName } : {}),\n ...(input.taxId !== undefined ? { taxId: input.taxId } : {}),\n ...(input.email !== undefined ? { email: input.email } : {}),\n ...(input.phone !== undefined ? { phone: input.phone } : {}),\n ...(input.website !== undefined ? { website: input.website } : {}),\n ...(input.logo !== undefined ? { logo: input.logo } : {}),\n ...(input.address !== undefined ? { address: input.address } : {}),\n ...(input.timezone !== undefined ? { timezone: input.timezone } : {}),\n ...(input.workSchedule !== undefined\n ? { workSchedule: input.workSchedule }\n : {}),\n ...(input.status !== undefined ? { status: input.status } : {}),\n };\n\n const updated = await this.employersCollection.update(\n id,\n {\n title: input.companyName ?? existing.title,\n data: updatedData,\n },\n authorId,\n );\n\n if (updated) {\n await this.engine.hooks.doAction(\"hrms.employer_updated\", updated);\n }\n return updated;\n }\n\n async listEmployers(\n query: {\n status?: \"active\" | \"inactive\";\n page?: number;\n limit?: number;\n } = {},\n ): Promise<PaginatedResult<EmployerItem>> {\n const limit = query.limit ?? 20;\n const offset = query.page ? (query.page - 1) * limit : 0;\n\n const result = await this.employersCollection.find({\n limit: 500,\n });\n\n let items = result.items;\n if (query.status) {\n items = items.filter((item) => item.data.status === query.status);\n }\n\n const total = items.length;\n const paginatedItems = items.slice(offset, offset + limit);\n\n return {\n items: paginatedItems,\n total,\n limit,\n offset,\n hasMore: offset + limit < total,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Employee Management\n // ---------------------------------------------------------------------------\n\n async createEmployee(\n input: CreateEmployeeInput,\n authorId?: string | null,\n ): Promise<EmployeeItem> {\n const employer = await this.getEmployer(input.employerId);\n if (!employer) {\n throw new Error(\n `[HRMSService] Employer with ID '${input.employerId}' not found.`,\n );\n }\n\n // Check unique employee number\n const existing = await this.getEmployeeByNumber(\n input.employerId,\n input.employeeNumber,\n );\n if (existing) {\n throw new Error(\n `[HRMSService] Employee number '${input.employeeNumber}' is already registered for this employer.`,\n );\n }\n\n const employeeData: EmployeeData = {\n employerId: input.employerId,\n userId: input.userId,\n employeeNumber: input.employeeNumber,\n firstName: input.firstName,\n lastName: input.lastName,\n email: input.email,\n phone: input.phone,\n avatar: input.avatar,\n jobTitle: input.jobTitle,\n employmentType: input.employmentType ?? \"full_time\",\n status: input.status ?? \"active\",\n hireDate: input.hireDate,\n managerId: input.managerId,\n emergencyContact: input.emergencyContact,\n documents: input.documents ?? [],\n salary: input.salary,\n notes: input.notes,\n };\n\n const title = `${input.firstName} ${input.lastName}`;\n const employee = await this.employeesCollection.create(\n {\n title,\n status: input.status === \"terminated\" ? \"draft\" : \"published\",\n data: employeeData,\n },\n authorId,\n );\n\n // Assign department taxonomy if provided\n if (input.departmentSlug) {\n const term = await this.engine.taxonomies.getTermBySlug(\n this.departmentsTaxonomy,\n input.departmentSlug,\n );\n if (term) {\n await this.engine.taxonomies.assignTerms(employee.id, [term.id]);\n }\n }\n\n await this.engine.hooks.doAction(\"hrms.employee_created\", employee);\n return employee;\n }\n\n async getEmployee(id: string): Promise<EmployeeItem | null> {\n return this.employeesCollection.findById(id);\n }\n\n async getEmployeeByNumber(\n employerId: string,\n employeeNumber: string,\n ): Promise<EmployeeItem | null> {\n const all = await this.employeesCollection.find({ limit: 500 });\n return (\n all.items.find(\n (e) =>\n e.data.employerId === employerId &&\n e.data.employeeNumber === employeeNumber,\n ) ?? null\n );\n }\n\n async updateEmployee(\n id: string,\n input: UpdateEmployeeInput,\n authorId?: string | null,\n ): Promise<EmployeeItem | null> {\n const existing = await this.getEmployee(id);\n if (!existing) return null;\n\n const updatedData: EmployeeData = {\n ...existing.data,\n ...(input.employerId !== undefined\n ? { employerId: input.employerId }\n : {}),\n ...(input.userId !== undefined ? { userId: input.userId } : {}),\n ...(input.employeeNumber !== undefined\n ? { employeeNumber: input.employeeNumber }\n : {}),\n ...(input.firstName !== undefined ? { firstName: input.firstName } : {}),\n ...(input.lastName !== undefined ? { lastName: input.lastName } : {}),\n ...(input.email !== undefined ? { email: input.email } : {}),\n ...(input.phone !== undefined ? { phone: input.phone } : {}),\n ...(input.avatar !== undefined ? { avatar: input.avatar } : {}),\n ...(input.jobTitle !== undefined ? { jobTitle: input.jobTitle } : {}),\n ...(input.employmentType !== undefined\n ? { employmentType: input.employmentType }\n : {}),\n ...(input.status !== undefined ? { status: input.status } : {}),\n ...(input.hireDate !== undefined ? { hireDate: input.hireDate } : {}),\n ...(input.terminationDate !== undefined\n ? { terminationDate: input.terminationDate }\n : {}),\n ...(input.managerId !== undefined ? { managerId: input.managerId } : {}),\n ...(input.emergencyContact !== undefined\n ? { emergencyContact: input.emergencyContact }\n : {}),\n ...(input.documents !== undefined ? { documents: input.documents } : {}),\n ...(input.salary !== undefined ? { salary: input.salary } : {}),\n ...(input.notes !== undefined ? { notes: input.notes } : {}),\n };\n\n const title =\n input.firstName || input.lastName\n ? `${updatedData.firstName} ${updatedData.lastName}`\n : existing.title;\n\n const updated = await this.employeesCollection.update(\n id,\n {\n title,\n data: updatedData,\n },\n authorId,\n );\n\n if (updated) {\n if (input.departmentSlug) {\n const term = await this.engine.taxonomies.getTermBySlug(\n this.departmentsTaxonomy,\n input.departmentSlug,\n );\n if (term) {\n await this.engine.taxonomies.assignTerms(id, [term.id]);\n }\n }\n await this.engine.hooks.doAction(\"hrms.employee_updated\", updated);\n }\n\n return updated;\n }\n\n async deleteEmployee(id: string): Promise<boolean> {\n const deleted = await this.employeesCollection.delete(id);\n if (deleted) {\n await this.engine.hooks.doAction(\"hrms.employee_deleted\", id);\n }\n return deleted;\n }\n\n async listEmployees(\n query: HRMSEmployeeQuery = {},\n ): Promise<PaginatedResult<EmployeeItem>> {\n const limit = query.limit ?? 20;\n const offset = query.page ? (query.page - 1) * limit : 0;\n\n let termIds: string[] | undefined;\n if (query.department) {\n const term = await this.engine.taxonomies.getTermBySlug(\n this.departmentsTaxonomy,\n query.department,\n );\n if (term) {\n termIds = [term.id];\n } else {\n return { items: [], total: 0, limit, offset, hasMore: false };\n }\n }\n\n const result = await this.employeesCollection.find({\n termIds,\n limit: 1000,\n });\n\n let items = result.items;\n\n if (query.employerId) {\n items = items.filter((e) => e.data.employerId === query.employerId);\n }\n if (query.employmentType) {\n items = items.filter(\n (e) => e.data.employmentType === query.employmentType,\n );\n }\n if (query.status) {\n items = items.filter((e) => e.data.status === query.status);\n }\n if (query.search) {\n const s = query.search.toLowerCase();\n items = items.filter(\n (e) =>\n e.data.firstName.toLowerCase().includes(s) ||\n e.data.lastName.toLowerCase().includes(s) ||\n e.data.email.toLowerCase().includes(s) ||\n e.data.employeeNumber.toLowerCase().includes(s) ||\n (e.data.jobTitle && e.data.jobTitle.toLowerCase().includes(s)),\n );\n }\n\n const total = items.length;\n const paginatedItems = items.slice(offset, offset + limit);\n\n return {\n items: paginatedItems,\n total,\n limit,\n offset,\n hasMore: offset + limit < total,\n };\n }\n\n async getDirectReports(managerId: string): Promise<EmployeeItem[]> {\n const all = await this.employeesCollection.find({ limit: 1000 });\n return all.items.filter((e) => e.data.managerId === managerId);\n }\n\n // ---------------------------------------------------------------------------\n // Attendance & Time Tracking\n // ---------------------------------------------------------------------------\n\n private parseTimeToMinutes(timeStr: string): number {\n const [hours, minutes] = timeStr.split(\":\").map((v) => parseInt(v, 10));\n return (hours || 0) * 60 + (minutes || 0);\n }\n\n private formatDateString(date: Date, timezone?: string): string {\n if (!timezone || timezone === \"UTC\") {\n return date.toISOString().slice(0, 10);\n }\n try {\n const formatter = new Intl.DateTimeFormat(\"en-CA\", {\n timeZone: timezone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n });\n return formatter.format(date);\n } catch {\n return date.toISOString().slice(0, 10);\n }\n }\n\n private getHoursAndMinutes(\n date: Date,\n timezone?: string,\n ): { hours: number; minutes: number } {\n if (!timezone || timezone === \"UTC\") {\n return { hours: date.getUTCHours(), minutes: date.getUTCMinutes() };\n }\n try {\n const formatter = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: timezone,\n hour: \"numeric\",\n minute: \"numeric\",\n hour12: false,\n });\n const parts = formatter.formatToParts(date);\n const hoursPart = parts.find((p) => p.type === \"hour\");\n const minutesPart = parts.find((p) => p.type === \"minute\");\n return {\n hours: hoursPart ? parseInt(hoursPart.value, 10) : date.getUTCHours(),\n minutes: minutesPart\n ? parseInt(minutesPart.value, 10)\n : date.getUTCMinutes(),\n };\n } catch {\n return { hours: date.getUTCHours(), minutes: date.getUTCMinutes() };\n }\n }\n\n /**\n * Check in an employee for today (or specified timestamp).\n */\n async checkIn(input: CheckInInput): Promise<AttendanceItem> {\n const employee = await this.getEmployee(input.employeeId);\n if (!employee) {\n throw new Error(\n `[HRMSService] Employee with ID '${input.employeeId}' not found.`,\n );\n }\n\n const employer = await this.getEmployer(employee.data.employerId);\n const timezone = employer?.data?.timezone ?? \"UTC\";\n\n const checkInDate = input.timestamp\n ? new Date(input.timestamp)\n : new Date();\n const dateStr = this.formatDateString(checkInDate, timezone);\n\n // Verify not already checked in\n const existing = await this.getDailyAttendance(employee.id, dateStr);\n if (existing && existing.data.checkInAt) {\n throw new Error(\n `[HRMSService] Employee '${employee.id}' is already checked in for date ${dateStr}.`,\n );\n }\n\n // Determine punctuality against employer schedule\n const schedule = employer?.data?.workSchedule;\n const schedStart = schedule?.startTime ?? this.workScheduleStart;\n const grace = schedule?.gracePeriodMinutes ?? this.gracePeriodMinutes;\n\n const schedMinutes = this.parseTimeToMinutes(schedStart);\n const { hours: punchHours, minutes: punchMins } = this.getHoursAndMinutes(\n checkInDate,\n timezone,\n );\n const punchMinutes = punchHours * 60 + punchMins;\n const isLate = punchMinutes > schedMinutes + grace;\n\n const status: AttendanceStatus = isLate ? \"late\" : \"present\";\n\n const attendanceData: AttendanceData = {\n employerId: employee.data.employerId,\n employeeId: employee.id,\n date: dateStr,\n checkInAt: checkInDate.toISOString(),\n totalHours: 0,\n overtimeHours: 0,\n status,\n location: input.location,\n notes: input.notes,\n };\n\n const attendance = await this.attendanceCollection.create({\n title: `${employee.title} - ${dateStr}`,\n status: \"published\",\n data: attendanceData,\n });\n\n await this.engine.hooks.doAction(\"hrms.checked_in\", attendance, employee);\n return attendance;\n }\n\n /**\n * Check out an employee for today (or specified timestamp).\n */\n async checkOut(input: CheckOutInput): Promise<AttendanceItem> {\n const employee = await this.getEmployee(input.employeeId);\n if (!employee) {\n throw new Error(\n `[HRMSService] Employee with ID '${input.employeeId}' not found.`,\n );\n }\n\n const employer = await this.getEmployer(employee.data.employerId);\n const timezone = employer?.data?.timezone ?? \"UTC\";\n\n const checkOutDate = input.timestamp\n ? new Date(input.timestamp)\n : new Date();\n const dateStr = this.formatDateString(checkOutDate, timezone);\n\n const record = await this.getDailyAttendance(employee.id, dateStr);\n if (!record || !record.data.checkInAt) {\n throw new Error(\n `[HRMSService] No active check-in record found for employee '${employee.id}' on ${dateStr}.`,\n );\n }\n\n if (record.data.checkOutAt) {\n throw new Error(\n `[HRMSService] Employee '${employee.id}' has already checked out for date ${dateStr}.`,\n );\n }\n\n const checkInDate = new Date(record.data.checkInAt);\n const durationMs = Math.max(\n 0,\n checkOutDate.getTime() - checkInDate.getTime(),\n );\n const totalHours = Math.round((durationMs / (1000 * 60 * 60)) * 100) / 100;\n\n const standardHours =\n employer?.data?.workSchedule?.standardHoursPerDay ??\n this.standardWorkDayHours;\n const overtimeHours = Math.max(\n 0,\n Math.round((totalHours - standardHours) * 100) / 100,\n );\n\n let status = record.data.status;\n if (totalHours < standardHours / 2 && status === \"present\") {\n status = \"half_day\";\n }\n\n const updatedData: AttendanceData = {\n ...record.data,\n checkOutAt: checkOutDate.toISOString(),\n totalHours,\n overtimeHours,\n status,\n ...(input.location ? { location: input.location } : {}),\n ...(input.notes ? { notes: input.notes } : {}),\n };\n\n const updated = await this.attendanceCollection.update(record.id, {\n data: updatedData,\n });\n\n if (!updated) {\n throw new Error(\n `[HRMSService] Failed to update attendance record for '${employee.id}'.`,\n );\n }\n\n await this.engine.hooks.doAction(\"hrms.checked_out\", updated, employee);\n return updated;\n }\n\n async getDailyAttendance(\n employeeId: string,\n date: string,\n ): Promise<AttendanceItem | null> {\n const all = await this.attendanceCollection.find({ limit: 1000 });\n return (\n all.items.find(\n (a) => a.data.employeeId === employeeId && a.data.date === date,\n ) ?? null\n );\n }\n\n async recordAttendanceManual(\n input: RecordAttendanceManualInput,\n ): Promise<AttendanceItem> {\n const existing = await this.getDailyAttendance(\n input.employeeId,\n input.date,\n );\n\n const attendanceData: AttendanceData = {\n employerId: input.employerId,\n employeeId: input.employeeId,\n date: input.date,\n checkInAt: input.checkInAt,\n checkOutAt: input.checkOutAt,\n totalHours: input.totalHours ?? 0,\n overtimeHours: input.overtimeHours ?? 0,\n status: input.status ?? \"present\",\n location: input.location,\n notes: input.notes,\n };\n\n if (existing) {\n const updated = await this.attendanceCollection.update(existing.id, {\n data: attendanceData,\n });\n if (!updated) {\n throw new Error(\n `[HRMSService] Failed to update attendance for '${input.employeeId}'.`,\n );\n }\n return updated;\n }\n\n return this.attendanceCollection.create({\n title: `${input.employeeId} - ${input.date}`,\n status: \"published\",\n data: attendanceData,\n });\n }\n\n async listAttendance(\n query: HRMSAttendanceQuery = {},\n ): Promise<PaginatedResult<AttendanceItem>> {\n const limit = query.limit ?? 30;\n const offset = query.page ? (query.page - 1) * limit : 0;\n\n const result = await this.attendanceCollection.find({ limit: 2000 });\n let items = result.items;\n\n if (query.employerId) {\n items = items.filter((a) => a.data.employerId === query.employerId);\n }\n if (query.employeeId) {\n items = items.filter((a) => a.data.employeeId === query.employeeId);\n }\n if (query.date) {\n items = items.filter((a) => a.data.date === query.date);\n }\n if (query.startDate) {\n items = items.filter((a) => a.data.date >= query.startDate!);\n }\n if (query.endDate) {\n items = items.filter((a) => a.data.date <= query.endDate!);\n }\n if (query.status) {\n items = items.filter((a) => a.data.status === query.status);\n }\n\n const total = items.length;\n const paginatedItems = items.slice(offset, offset + limit);\n\n return {\n items: paginatedItems,\n total,\n limit,\n offset,\n hasMore: offset + limit < total,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Leave Types & Leave Requests\n // ---------------------------------------------------------------------------\n\n async createLeaveType(\n input: CreateLeaveTypeInput,\n authorId?: string | null,\n ): Promise<LeaveTypeItem> {\n const leaveTypeData: LeaveTypeData = {\n employerId: input.employerId,\n name: input.name,\n code: input.code.toUpperCase(),\n daysAllowedPerYear: input.daysAllowedPerYear,\n paid: input.paid ?? true,\n requiresApproval: input.requiresApproval ?? true,\n color: input.color,\n description: input.description,\n };\n\n const item = await this.leaveTypesCollection.create(\n {\n title: input.name,\n status: \"published\",\n data: leaveTypeData,\n },\n authorId,\n );\n\n await this.engine.hooks.doAction(\"hrms.leave_type_created\", item);\n return item;\n }\n\n async getLeaveType(id: string): Promise<LeaveTypeItem | null> {\n return this.leaveTypesCollection.findById(id);\n }\n\n async listLeaveTypes(employerId?: string): Promise<LeaveTypeItem[]> {\n const result = await this.leaveTypesCollection.find({ limit: 100 });\n if (!employerId) return result.items;\n\n return result.items.filter(\n (lt) => !lt.data.employerId || lt.data.employerId === employerId,\n );\n }\n\n /**\n * Calculate leave balance report for an employee for a given year.\n */\n async calculateLeaveBalance(\n employeeId: string,\n year?: number,\n ): Promise<EmployeeLeaveBalanceReport> {\n const targetYear = year ?? new Date().getFullYear();\n const employee = await this.getEmployee(employeeId);\n if (!employee) {\n throw new Error(\n `[HRMSService] Employee with ID '${employeeId}' not found.`,\n );\n }\n\n const leaveTypes = await this.listLeaveTypes(employee.data.employerId);\n\n // Retrieve all leave requests for employee in target year\n const allRequests = await this.leaveRequestsCollection.find({\n limit: 1000,\n });\n const yearStr = String(targetYear);\n const employeeRequests = allRequests.items.filter(\n (r) =>\n r.data.employeeId === employeeId &&\n (r.data.startDate.startsWith(yearStr) ||\n r.data.endDate.startsWith(yearStr)),\n );\n\n const balances: LeaveBalanceItem[] = leaveTypes.map((lt) => {\n const approved = employeeRequests.filter(\n (r) => r.data.leaveTypeId === lt.id && r.data.status === \"approved\",\n );\n const pending = employeeRequests.filter(\n (r) => r.data.leaveTypeId === lt.id && r.data.status === \"pending\",\n );\n\n const usedDays = approved.reduce(\n (sum, r) => sum + (r.data.daysCount || 0),\n 0,\n );\n const pendingDays = pending.reduce(\n (sum, r) => sum + (r.data.daysCount || 0),\n 0,\n );\n const allocatedDays = lt.data.daysAllowedPerYear ?? 0;\n const remainingDays = Math.max(0, allocatedDays - usedDays);\n\n return {\n leaveTypeId: lt.id,\n leaveTypeName: lt.data.name,\n leaveTypeCode: lt.data.code,\n allocatedDays,\n usedDays,\n pendingDays,\n remainingDays,\n };\n });\n\n const totalAllocated = balances.reduce(\n (sum, b) => sum + b.allocatedDays,\n 0,\n );\n const totalUsed = balances.reduce((sum, b) => sum + b.usedDays, 0);\n const totalRemaining = balances.reduce(\n (sum, b) => sum + b.remainingDays,\n 0,\n );\n\n const report: EmployeeLeaveBalanceReport = {\n employeeId,\n year: targetYear,\n balances,\n totalAllocated,\n totalUsed,\n totalRemaining,\n };\n\n return this.engine.hooks.applyFilters(\n \"hrms.calculate_leave_balance\",\n report,\n employeeId,\n targetYear,\n );\n }\n\n /**\n * Submit a new leave request.\n */\n async requestLeave(\n input: CreateLeaveRequestInput,\n authorId?: string | null,\n ): Promise<LeaveRequestItem> {\n const employee = await this.getEmployee(input.employeeId);\n if (!employee) {\n throw new Error(\n `[HRMSService] Employee with ID '${input.employeeId}' not found.`,\n );\n }\n\n const leaveType = await this.getLeaveType(input.leaveTypeId);\n if (!leaveType) {\n throw new Error(\n `[HRMSService] Leave type with ID '${input.leaveTypeId}' not found.`,\n );\n }\n\n if (input.startDate > input.endDate) {\n throw new Error(\n `[HRMSService] Start date '${input.startDate}' cannot be after end date '${input.endDate}'.`,\n );\n }\n\n const start = new Date(input.startDate);\n const end = new Date(input.endDate);\n const calculatedDays = Math.max(\n 1,\n Math.round((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24)) + 1,\n );\n const daysCount = input.daysCount ?? calculatedDays;\n\n // Balance check\n const startYear = start.getFullYear();\n const balanceReport = await this.calculateLeaveBalance(\n employee.id,\n startYear,\n );\n const balance = balanceReport.balances.find(\n (b) => b.leaveTypeId === leaveType.id,\n );\n\n if (\n balance &&\n leaveType.data.requiresApproval &&\n daysCount > balance.remainingDays\n ) {\n throw new Error(\n `[HRMSService] Insufficient leave balance for ${leaveType.data.name}. Requested: ${daysCount}, Remaining: ${balance.remainingDays}.`,\n );\n }\n\n const leaveRequestData: LeaveRequestData = {\n employerId: input.employerId ?? employee.data.employerId,\n employeeId: employee.id,\n leaveTypeId: leaveType.id,\n startDate: input.startDate,\n endDate: input.endDate,\n daysCount,\n reason: input.reason,\n status: \"pending\",\n };\n\n const item = await this.leaveRequestsCollection.create(\n {\n title: `${employee.title} - ${leaveType.data.name} (${input.startDate})`,\n status: \"published\",\n data: leaveRequestData,\n },\n authorId,\n );\n\n await this.engine.hooks.doAction(\"hrms.leave_requested\", item, employee);\n return item;\n }\n\n /**\n * Approve a pending leave request.\n */\n async approveLeave(input: ApproveLeaveInput): Promise<LeaveRequestItem> {\n const request = await this.leaveRequestsCollection.findById(\n input.requestId,\n );\n if (!request) {\n throw new Error(\n `[HRMSService] Leave request with ID '${input.requestId}' not found.`,\n );\n }\n\n if (request.data.status !== \"pending\") {\n throw new Error(\n `[HRMSService] Cannot approve leave request with status '${request.data.status}'.`,\n );\n }\n\n const updated = await this.leaveRequestsCollection.update(request.id, {\n data: {\n ...request.data,\n status: \"approved\",\n approvedBy: input.approverId,\n approvedAt: new Date().toISOString(),\n },\n });\n\n if (!updated) {\n throw new Error(`[HRMSService] Failed to update leave request.`);\n }\n\n await this.engine.hooks.doAction(\"hrms.leave_approved\", updated);\n return updated;\n }\n\n /**\n * Reject a pending leave request.\n */\n async rejectLeave(input: RejectLeaveInput): Promise<LeaveRequestItem> {\n const request = await this.leaveRequestsCollection.findById(\n input.requestId,\n );\n if (!request) {\n throw new Error(\n `[HRMSService] Leave request with ID '${input.requestId}' not found.`,\n );\n }\n\n if (request.data.status !== \"pending\") {\n throw new Error(\n `[HRMSService] Cannot reject leave request with status '${request.data.status}'.`,\n );\n }\n\n const updated = await this.leaveRequestsCollection.update(request.id, {\n data: {\n ...request.data,\n status: \"rejected\",\n approvedBy: input.approverId,\n rejectionReason: input.reason,\n approvedAt: new Date().toISOString(),\n },\n });\n\n if (!updated) {\n throw new Error(`[HRMSService] Failed to update leave request.`);\n }\n\n await this.engine.hooks.doAction(\"hrms.leave_rejected\", updated);\n return updated;\n }\n\n /**\n * Cancel a leave request.\n */\n async cancelLeave(requestId: string): Promise<LeaveRequestItem> {\n const request = await this.leaveRequestsCollection.findById(requestId);\n if (!request) {\n throw new Error(\n `[HRMSService] Leave request with ID '${requestId}' not found.`,\n );\n }\n\n if (request.data.status === \"cancelled\") {\n return request;\n }\n\n const updated = await this.leaveRequestsCollection.update(request.id, {\n data: {\n ...request.data,\n status: \"cancelled\",\n },\n });\n\n if (!updated) {\n throw new Error(`[HRMSService] Failed to cancel leave request.`);\n }\n\n await this.engine.hooks.doAction(\"hrms.leave_cancelled\", updated);\n return updated;\n }\n\n async listLeaveRequests(\n query: HRMSLeaveQuery = {},\n ): Promise<PaginatedResult<LeaveRequestItem>> {\n const limit = query.limit ?? 20;\n const offset = query.page ? (query.page - 1) * limit : 0;\n\n const result = await this.leaveRequestsCollection.find({ limit: 1000 });\n let items = result.items;\n\n if (query.employerId) {\n items = items.filter((r) => r.data.employerId === query.employerId);\n }\n if (query.employeeId) {\n items = items.filter((r) => r.data.employeeId === query.employeeId);\n }\n if (query.leaveTypeId) {\n items = items.filter((r) => r.data.leaveTypeId === query.leaveTypeId);\n }\n if (query.status) {\n items = items.filter((r) => r.data.status === query.status);\n }\n if (query.year) {\n const yearStr = String(query.year);\n items = items.filter(\n (r) =>\n r.data.startDate.startsWith(yearStr) ||\n r.data.endDate.startsWith(yearStr),\n );\n }\n\n const total = items.length;\n const paginatedItems = items.slice(offset, offset + limit);\n\n return {\n items: paginatedItems,\n total,\n limit,\n offset,\n hasMore: offset + limit < total,\n };\n }\n}\n","/**\n * @azlib/cms - Built-in HRMS Web Standard HTTP API Routes\n */\n\nimport type { CMSPluginContext } from \"../../core/plugin.js\";\nimport type { HRMSService } from \"./service.js\";\nimport type {\n CheckInInput,\n CheckOutInput,\n CreateEmployeeInput,\n CreateEmployerInput,\n CreateLeaveRequestInput,\n CreateLeaveTypeInput,\n HRMSPluginOptions,\n RecordAttendanceManualInput,\n UpdateEmployeeInput,\n UpdateEmployerInput,\n} from \"./types.js\";\n\nfunction json(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Access-Control-Allow-Origin\": \"*\",\n },\n });\n}\n\nfunction badRequest(message: string): Response {\n return json({ error: message }, 400);\n}\n\nfunction notFound(message: string): Response {\n return json({ error: message }, 404);\n}\n\nexport function registerHRMSRoutes(\n ctx: CMSPluginContext,\n service: HRMSService,\n options: HRMSPluginOptions = {},\n): void {\n const prefix = (options.apiPrefix ?? \"/api/hrms\").replace(/\\/+$/, \"\");\n\n // ---------------------------------------------------------------------------\n // Employer Endpoints\n // ---------------------------------------------------------------------------\n\n // GET /api/hrms/employers\n ctx.registerRoute(\"GET\", `${prefix}/employers`, async (_req, { url }) => {\n try {\n const status = url.searchParams.get(\"status\") as any;\n const pageStr = url.searchParams.get(\"page\");\n const limitStr = url.searchParams.get(\"limit\");\n const page = pageStr ? parseInt(pageStr, 10) : undefined;\n const limit = limitStr ? parseInt(limitStr, 10) : undefined;\n\n const result = await service.listEmployers({ status, page, limit });\n return json(result);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // POST /api/hrms/employers\n ctx.registerRoute(\"POST\", `${prefix}/employers`, async (req) => {\n try {\n const body = (await req.json()) as CreateEmployerInput;\n if (!body.companyName) {\n return badRequest(\"companyName is required.\");\n }\n const employer = await service.createEmployer(body);\n return json(employer, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // GET /api/hrms/employers/:id\n ctx.registerRoute(\n \"GET\",\n `${prefix}/employers/:id`,\n async (_req, { params }) => {\n try {\n const employer = await service.getEmployer(params.id);\n if (!employer) return notFound(`Employer '${params.id}' not found.`);\n return json(employer);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // PUT /api/hrms/employers/:id\n ctx.registerRoute(\n \"PUT\",\n `${prefix}/employers/:id`,\n async (req, { params }) => {\n try {\n const body = (await req.json()) as UpdateEmployerInput;\n const updated = await service.updateEmployer(params.id, body);\n if (!updated) return notFound(`Employer '${params.id}' not found.`);\n return json(updated);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // ---------------------------------------------------------------------------\n // Employee Endpoints\n // ---------------------------------------------------------------------------\n\n // GET /api/hrms/employees\n ctx.registerRoute(\"GET\", `${prefix}/employees`, async (_req, { url }) => {\n try {\n const employerId = url.searchParams.get(\"employerId\") ?? undefined;\n const department = url.searchParams.get(\"department\") ?? undefined;\n const employmentType = url.searchParams.get(\"employmentType\") as any;\n const status = url.searchParams.get(\"status\") as any;\n const search = url.searchParams.get(\"search\") ?? undefined;\n const pageStr = url.searchParams.get(\"page\");\n const limitStr = url.searchParams.get(\"limit\");\n const page = pageStr ? parseInt(pageStr, 10) : undefined;\n const limit = limitStr ? parseInt(limitStr, 10) : undefined;\n\n const result = await service.listEmployees({\n employerId,\n department,\n employmentType,\n status,\n search,\n page,\n limit,\n });\n return json(result);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // POST /api/hrms/employees\n ctx.registerRoute(\"POST\", `${prefix}/employees`, async (req) => {\n try {\n const body = (await req.json()) as CreateEmployeeInput;\n if (!body.employerId) return badRequest(\"employerId is required.\");\n if (!body.employeeNumber)\n return badRequest(\"employeeNumber is required.\");\n if (!body.firstName || !body.lastName)\n return badRequest(\"firstName and lastName are required.\");\n if (!body.email) return badRequest(\"email is required.\");\n\n const employee = await service.createEmployee(body);\n return json(employee, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // GET /api/hrms/employees/:id\n ctx.registerRoute(\n \"GET\",\n `${prefix}/employees/:id`,\n async (_req, { params }) => {\n try {\n const employee = await service.getEmployee(params.id);\n if (!employee) return notFound(`Employee '${params.id}' not found.`);\n return json(employee);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // PUT /api/hrms/employees/:id\n ctx.registerRoute(\n \"PUT\",\n `${prefix}/employees/:id`,\n async (req, { params }) => {\n try {\n const body = (await req.json()) as UpdateEmployeeInput;\n const updated = await service.updateEmployee(params.id, body);\n if (!updated) return notFound(`Employee '${params.id}' not found.`);\n return json(updated);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // DELETE /api/hrms/employees/:id\n ctx.registerRoute(\n \"DELETE\",\n `${prefix}/employees/:id`,\n async (_req, { params }) => {\n try {\n const ok = await service.deleteEmployee(params.id);\n if (!ok) return notFound(`Employee '${params.id}' not found.`);\n return json({ success: true });\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // GET /api/hrms/employees/:id/leave-balance\n ctx.registerRoute(\n \"GET\",\n `${prefix}/employees/:id/leave-balance`,\n async (_req, { params, url }) => {\n try {\n const yearStr = url.searchParams.get(\"year\");\n const year = yearStr ? parseInt(yearStr, 10) : undefined;\n const report = await service.calculateLeaveBalance(params.id, year);\n return json(report);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // GET /api/hrms/employees/:id/direct-reports\n ctx.registerRoute(\n \"GET\",\n `${prefix}/employees/:id/direct-reports`,\n async (_req, { params }) => {\n try {\n const reports = await service.getDirectReports(params.id);\n return json({ items: reports, total: reports.length });\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // ---------------------------------------------------------------------------\n // Attendance Endpoints\n // ---------------------------------------------------------------------------\n\n // POST /api/hrms/attendance/check-in\n ctx.registerRoute(\"POST\", `${prefix}/attendance/check-in`, async (req) => {\n try {\n const body = (await req.json()) as CheckInInput;\n if (!body.employeeId) return badRequest(\"employeeId is required.\");\n const record = await service.checkIn(body);\n return json(record, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // POST /api/hrms/attendance/check-out\n ctx.registerRoute(\"POST\", `${prefix}/attendance/check-out`, async (req) => {\n try {\n const body = (await req.json()) as CheckOutInput;\n if (!body.employeeId) return badRequest(\"employeeId is required.\");\n const record = await service.checkOut(body);\n return json(record);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // GET /api/hrms/attendance\n ctx.registerRoute(\"GET\", `${prefix}/attendance`, async (_req, { url }) => {\n try {\n const employerId = url.searchParams.get(\"employerId\") ?? undefined;\n const employeeId = url.searchParams.get(\"employeeId\") ?? undefined;\n const date = url.searchParams.get(\"date\") ?? undefined;\n const startDate = url.searchParams.get(\"startDate\") ?? undefined;\n const endDate = url.searchParams.get(\"endDate\") ?? undefined;\n const status = url.searchParams.get(\"status\") as any;\n const pageStr = url.searchParams.get(\"page\");\n const limitStr = url.searchParams.get(\"limit\");\n const page = pageStr ? parseInt(pageStr, 10) : undefined;\n const limit = limitStr ? parseInt(limitStr, 10) : undefined;\n\n const result = await service.listAttendance({\n employerId,\n employeeId,\n date,\n startDate,\n endDate,\n status,\n page,\n limit,\n });\n return json(result);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // POST /api/hrms/attendance/manual\n ctx.registerRoute(\"POST\", `${prefix}/attendance/manual`, async (req) => {\n try {\n const body = (await req.json()) as RecordAttendanceManualInput;\n if (\n !body.employerId ||\n !body.employeeId ||\n !body.date ||\n !body.checkInAt\n ) {\n return badRequest(\n \"employerId, employeeId, date, and checkInAt are required.\",\n );\n }\n const record = await service.recordAttendanceManual(body);\n return json(record, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // ---------------------------------------------------------------------------\n // Leave Types Endpoints\n // ---------------------------------------------------------------------------\n\n // GET /api/hrms/leave-types\n ctx.registerRoute(\"GET\", `${prefix}/leave-types`, async (_req, { url }) => {\n try {\n const employerId = url.searchParams.get(\"employerId\") ?? undefined;\n const types = await service.listLeaveTypes(employerId);\n return json({ items: types, total: types.length });\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // POST /api/hrms/leave-types\n ctx.registerRoute(\"POST\", `${prefix}/leave-types`, async (req) => {\n try {\n const body = (await req.json()) as CreateLeaveTypeInput;\n if (!body.name || !body.code || body.daysAllowedPerYear === undefined) {\n return badRequest(\"name, code, and daysAllowedPerYear are required.\");\n }\n const leaveType = await service.createLeaveType(body);\n return json(leaveType, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // GET /api/hrms/leave-types/:id\n ctx.registerRoute(\n \"GET\",\n `${prefix}/leave-types/:id`,\n async (_req, { params }) => {\n try {\n const leaveType = await service.getLeaveType(params.id);\n if (!leaveType) return notFound(`Leave type '${params.id}' not found.`);\n return json(leaveType);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // ---------------------------------------------------------------------------\n // Leave Requests Endpoints\n // ---------------------------------------------------------------------------\n\n // GET /api/hrms/leave-requests\n ctx.registerRoute(\n \"GET\",\n `${prefix}/leave-requests`,\n async (_req, { url }) => {\n try {\n const employerId = url.searchParams.get(\"employerId\") ?? undefined;\n const employeeId = url.searchParams.get(\"employeeId\") ?? undefined;\n const leaveTypeId = url.searchParams.get(\"leaveTypeId\") ?? undefined;\n const status = url.searchParams.get(\"status\") as any;\n const yearStr = url.searchParams.get(\"year\");\n const year = yearStr ? parseInt(yearStr, 10) : undefined;\n const pageStr = url.searchParams.get(\"page\");\n const limitStr = url.searchParams.get(\"limit\");\n const page = pageStr ? parseInt(pageStr, 10) : undefined;\n const limit = limitStr ? parseInt(limitStr, 10) : undefined;\n\n const result = await service.listLeaveRequests({\n employerId,\n employeeId,\n leaveTypeId,\n status,\n year,\n page,\n limit,\n });\n return json(result);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // POST /api/hrms/leave-requests\n ctx.registerRoute(\"POST\", `${prefix}/leave-requests`, async (req) => {\n try {\n const body = (await req.json()) as CreateLeaveRequestInput;\n if (\n !body.employeeId ||\n !body.leaveTypeId ||\n !body.startDate ||\n !body.endDate\n ) {\n return badRequest(\n \"employeeId, leaveTypeId, startDate, and endDate are required.\",\n );\n }\n const request = await service.requestLeave(body);\n return json(request, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // POST /api/hrms/leave-requests/:id/approve\n ctx.registerRoute(\n \"POST\",\n `${prefix}/leave-requests/:id/approve`,\n async (req, { params }) => {\n try {\n const body = (await req.json().catch(() => ({}))) as {\n approverId?: string;\n };\n const approverId = body.approverId ?? \"admin\";\n const approved = await service.approveLeave({\n requestId: params.id,\n approverId,\n });\n return json(approved);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // POST /api/hrms/leave-requests/:id/reject\n ctx.registerRoute(\n \"POST\",\n `${prefix}/leave-requests/:id/reject`,\n async (req, { params }) => {\n try {\n const body = (await req.json().catch(() => ({}))) as {\n approverId?: string;\n reason?: string;\n };\n const approverId = body.approverId ?? \"admin\";\n const rejected = await service.rejectLeave({\n requestId: params.id,\n approverId,\n reason: body.reason,\n });\n return json(rejected);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n\n // POST /api/hrms/leave-requests/:id/cancel\n ctx.registerRoute(\n \"POST\",\n `${prefix}/leave-requests/:id/cancel`,\n async (_req, { params }) => {\n try {\n const cancelled = await service.cancelLeave(params.id);\n return json(cancelled);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n },\n );\n}\n","/**\n * @azlib/cms - Built-in HRMS Headless Client Extension\n */\n\nimport type { CMSClient } from \"../../client/cms-client.js\";\nimport type { PaginatedResult } from \"../../core/types.js\";\nimport { HRMSService } from \"./service.js\";\nimport type {\n ApproveLeaveInput,\n AttendanceItem,\n CheckInInput,\n CheckOutInput,\n CreateEmployeeInput,\n CreateEmployerInput,\n CreateLeaveRequestInput,\n CreateLeaveTypeInput,\n EmployeeItem,\n EmployeeLeaveBalanceReport,\n EmployerItem,\n HRMSAttendanceQuery,\n HRMSEmployeeQuery,\n HRMSLeaveQuery,\n HRMSPluginOptions,\n LeaveRequestItem,\n LeaveTypeItem,\n RecordAttendanceManualInput,\n RejectLeaveInput,\n UpdateEmployeeInput,\n UpdateEmployerInput,\n} from \"./types.js\";\n\nexport class HRMSClient {\n private service?: HRMSService;\n private prefix: string;\n\n constructor(\n private client: CMSClient,\n private options: HRMSPluginOptions = {},\n ) {\n this.prefix = (options.apiPrefix ?? \"/api/hrms\").replace(/\\/+$/, \"\");\n const engine = client.getEngine();\n if (engine) {\n this.service = new HRMSService(engine, options);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Employers API\n // ---------------------------------------------------------------------------\n\n readonly employers = {\n find: async (\n query: {\n status?: \"active\" | \"inactive\";\n page?: number;\n limit?: number;\n } = {},\n ): Promise<PaginatedResult<EmployerItem>> => {\n if (this.service) {\n return this.service.listEmployers(query);\n }\n const params = new URLSearchParams();\n if (query.status) params.set(\"status\", query.status);\n if (query.page) params.set(\"page\", String(query.page));\n if (query.limit) params.set(\"limit\", String(query.limit));\n const q = params.toString() ? `?${params.toString()}` : \"\";\n return this.client.request<PaginatedResult<EmployerItem>>(\n `${this.prefix}/employers${q}`,\n );\n },\n\n get: async (id: string): Promise<EmployerItem | null> => {\n if (this.service) {\n return this.service.getEmployer(id);\n }\n return this.client.request<EmployerItem | null>(\n `${this.prefix}/employers/${encodeURIComponent(id)}`,\n );\n },\n\n create: async (input: CreateEmployerInput): Promise<EmployerItem> => {\n if (this.service) {\n return this.service.createEmployer(input);\n }\n return this.client.request<EmployerItem>(`${this.prefix}/employers`, {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n },\n\n update: async (\n id: string,\n input: UpdateEmployerInput,\n ): Promise<EmployerItem | null> => {\n if (this.service) {\n return this.service.updateEmployer(id, input);\n }\n return this.client.request<EmployerItem | null>(\n `${this.prefix}/employers/${encodeURIComponent(id)}`,\n {\n method: \"PUT\",\n body: JSON.stringify(input),\n },\n );\n },\n };\n\n // ---------------------------------------------------------------------------\n // Employees API\n // ---------------------------------------------------------------------------\n\n readonly employees = {\n find: async (\n query: HRMSEmployeeQuery = {},\n ): Promise<PaginatedResult<EmployeeItem>> => {\n if (this.service) {\n return this.service.listEmployees(query);\n }\n const params = new URLSearchParams();\n if (query.employerId) params.set(\"employerId\", query.employerId);\n if (query.department) params.set(\"department\", query.department);\n if (query.employmentType)\n params.set(\"employmentType\", query.employmentType);\n if (query.status) params.set(\"status\", query.status);\n if (query.search) params.set(\"search\", query.search);\n if (query.page) params.set(\"page\", String(query.page));\n if (query.limit) params.set(\"limit\", String(query.limit));\n const q = params.toString() ? `?${params.toString()}` : \"\";\n return this.client.request<PaginatedResult<EmployeeItem>>(\n `${this.prefix}/employees${q}`,\n );\n },\n\n get: async (id: string): Promise<EmployeeItem | null> => {\n if (this.service) {\n return this.service.getEmployee(id);\n }\n return this.client.request<EmployeeItem | null>(\n `${this.prefix}/employees/${encodeURIComponent(id)}`,\n );\n },\n\n getByNumber: async (\n employerId: string,\n employeeNumber: string,\n ): Promise<EmployeeItem | null> => {\n if (this.service) {\n return this.service.getEmployeeByNumber(employerId, employeeNumber);\n }\n const res = await this.employees.find({\n employerId,\n search: employeeNumber,\n });\n return (\n res.items.find((e) => e.data.employeeNumber === employeeNumber) ?? null\n );\n },\n\n create: async (input: CreateEmployeeInput): Promise<EmployeeItem> => {\n if (this.service) {\n return this.service.createEmployee(input);\n }\n return this.client.request<EmployeeItem>(`${this.prefix}/employees`, {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n },\n\n update: async (\n id: string,\n input: UpdateEmployeeInput,\n ): Promise<EmployeeItem | null> => {\n if (this.service) {\n return this.service.updateEmployee(id, input);\n }\n return this.client.request<EmployeeItem | null>(\n `${this.prefix}/employees/${encodeURIComponent(id)}`,\n {\n method: \"PUT\",\n body: JSON.stringify(input),\n },\n );\n },\n\n delete: async (id: string): Promise<boolean> => {\n if (this.service) {\n return this.service.deleteEmployee(id);\n }\n const res = await this.client.request<{ success: boolean }>(\n `${this.prefix}/employees/${encodeURIComponent(id)}`,\n { method: \"DELETE\" },\n );\n return res.success;\n },\n\n getLeaveBalance: async (\n employeeId: string,\n year?: number,\n ): Promise<EmployeeLeaveBalanceReport> => {\n if (this.service) {\n return this.service.calculateLeaveBalance(employeeId, year);\n }\n const q = year ? `?year=${year}` : \"\";\n return this.client.request<EmployeeLeaveBalanceReport>(\n `${this.prefix}/employees/${encodeURIComponent(employeeId)}/leave-balance${q}`,\n );\n },\n\n getDirectReports: async (managerId: string): Promise<EmployeeItem[]> => {\n if (this.service) {\n return this.service.getDirectReports(managerId);\n }\n const res = await this.client.request<{ items: EmployeeItem[] }>(\n `${this.prefix}/employees/${encodeURIComponent(managerId)}/direct-reports`,\n );\n return res.items;\n },\n };\n\n // ---------------------------------------------------------------------------\n // Attendance API\n // ---------------------------------------------------------------------------\n\n readonly attendance = {\n checkIn: async (input: CheckInInput): Promise<AttendanceItem> => {\n if (this.service) {\n return this.service.checkIn(input);\n }\n return this.client.request<AttendanceItem>(\n `${this.prefix}/attendance/check-in`,\n {\n method: \"POST\",\n body: JSON.stringify(input),\n },\n );\n },\n\n checkOut: async (input: CheckOutInput): Promise<AttendanceItem> => {\n if (this.service) {\n return this.service.checkOut(input);\n }\n return this.client.request<AttendanceItem>(\n `${this.prefix}/attendance/check-out`,\n {\n method: \"POST\",\n body: JSON.stringify(input),\n },\n );\n },\n\n getDaily: async (\n employeeId: string,\n date: string,\n ): Promise<AttendanceItem | null> => {\n if (this.service) {\n return this.service.getDailyAttendance(employeeId, date);\n }\n const res = await this.attendance.find({ employeeId, date });\n return res.items[0] ?? null;\n },\n\n find: async (\n query: HRMSAttendanceQuery = {},\n ): Promise<PaginatedResult<AttendanceItem>> => {\n if (this.service) {\n return this.service.listAttendance(query);\n }\n const params = new URLSearchParams();\n if (query.employerId) params.set(\"employerId\", query.employerId);\n if (query.employeeId) params.set(\"employeeId\", query.employeeId);\n if (query.date) params.set(\"date\", query.date);\n if (query.startDate) params.set(\"startDate\", query.startDate);\n if (query.endDate) params.set(\"endDate\", query.endDate);\n if (query.status) params.set(\"status\", query.status);\n if (query.page) params.set(\"page\", String(query.page));\n if (query.limit) params.set(\"limit\", String(query.limit));\n const q = params.toString() ? `?${params.toString()}` : \"\";\n return this.client.request<PaginatedResult<AttendanceItem>>(\n `${this.prefix}/attendance${q}`,\n );\n },\n\n recordManual: async (\n input: RecordAttendanceManualInput,\n ): Promise<AttendanceItem> => {\n if (this.service) {\n return this.service.recordAttendanceManual(input);\n }\n return this.client.request<AttendanceItem>(\n `${this.prefix}/attendance/manual`,\n {\n method: \"POST\",\n body: JSON.stringify(input),\n },\n );\n },\n };\n\n // ---------------------------------------------------------------------------\n // Leaves API\n // ---------------------------------------------------------------------------\n\n readonly leaves = {\n listTypes: async (employerId?: string): Promise<LeaveTypeItem[]> => {\n if (this.service) {\n return this.service.listLeaveTypes(employerId);\n }\n const q = employerId\n ? `?employerId=${encodeURIComponent(employerId)}`\n : \"\";\n const res = await this.client.request<{ items: LeaveTypeItem[] }>(\n `${this.prefix}/leave-types${q}`,\n );\n return res.items;\n },\n\n createType: async (input: CreateLeaveTypeInput): Promise<LeaveTypeItem> => {\n if (this.service) {\n return this.service.createLeaveType(input);\n }\n return this.client.request<LeaveTypeItem>(`${this.prefix}/leave-types`, {\n method: \"POST\",\n body: JSON.stringify(input),\n });\n },\n\n getType: async (id: string): Promise<LeaveTypeItem | null> => {\n if (this.service) {\n return this.service.getLeaveType(id);\n }\n return this.client.request<LeaveTypeItem | null>(\n `${this.prefix}/leave-types/${encodeURIComponent(id)}`,\n );\n },\n\n findRequests: async (\n query: HRMSLeaveQuery = {},\n ): Promise<PaginatedResult<LeaveRequestItem>> => {\n if (this.service) {\n return this.service.listLeaveRequests(query);\n }\n const params = new URLSearchParams();\n if (query.employerId) params.set(\"employerId\", query.employerId);\n if (query.employeeId) params.set(\"employeeId\", query.employeeId);\n if (query.leaveTypeId) params.set(\"leaveTypeId\", query.leaveTypeId);\n if (query.status) params.set(\"status\", query.status);\n if (query.year) params.set(\"year\", String(query.year));\n if (query.page) params.set(\"page\", String(query.page));\n if (query.limit) params.set(\"limit\", String(query.limit));\n const q = params.toString() ? `?${params.toString()}` : \"\";\n return this.client.request<PaginatedResult<LeaveRequestItem>>(\n `${this.prefix}/leave-requests${q}`,\n );\n },\n\n request: async (\n input: CreateLeaveRequestInput,\n ): Promise<LeaveRequestItem> => {\n if (this.service) {\n return this.service.requestLeave(input);\n }\n return this.client.request<LeaveRequestItem>(\n `${this.prefix}/leave-requests`,\n {\n method: \"POST\",\n body: JSON.stringify(input),\n },\n );\n },\n\n approve: async (input: ApproveLeaveInput): Promise<LeaveRequestItem> => {\n if (this.service) {\n return this.service.approveLeave(input);\n }\n return this.client.request<LeaveRequestItem>(\n `${this.prefix}/leave-requests/${encodeURIComponent(input.requestId)}/approve`,\n {\n method: \"POST\",\n body: JSON.stringify({ approverId: input.approverId }),\n },\n );\n },\n\n reject: async (input: RejectLeaveInput): Promise<LeaveRequestItem> => {\n if (this.service) {\n return this.service.rejectLeave(input);\n }\n return this.client.request<LeaveRequestItem>(\n `${this.prefix}/leave-requests/${encodeURIComponent(input.requestId)}/reject`,\n {\n method: \"POST\",\n body: JSON.stringify({\n approverId: input.approverId,\n reason: input.reason,\n }),\n },\n );\n },\n\n cancel: async (requestId: string): Promise<LeaveRequestItem> => {\n if (this.service) {\n return this.service.cancelLeave(requestId);\n }\n return this.client.request<LeaveRequestItem>(\n `${this.prefix}/leave-requests/${encodeURIComponent(requestId)}/cancel`,\n { method: \"POST\" },\n );\n },\n };\n}\n\n/**\n * Get or create an HRMSClient adapter for a CMSClient.\n */\nexport function getHRMSClient(\n client: CMSClient,\n options?: HRMSPluginOptions,\n): HRMSClient {\n return new HRMSClient(client, options);\n}\n","/**\n * @azlib/cms - Built-in HRMS Plugin\n */\n\nimport { definePlugin, type CMSPlugin } from \"../../core/plugin.js\";\nimport type { CMSEngine } from \"../../core/engine.js\";\nimport {\n createAttendanceCollection,\n createEmployeeCollection,\n createEmployerCollection,\n createHRMSTaxonomies,\n createLeaveRequestCollection,\n createLeaveTypeCollection,\n} from \"./schemas.js\";\nimport { HRMSService } from \"./service.js\";\nimport { registerHRMSRoutes } from \"./routes.js\";\nimport type { HRMSPluginOptions } from \"./types.js\";\n\nexport * from \"./types.js\";\nexport * from \"./schemas.js\";\nexport * from \"./service.js\";\nexport * from \"./client.js\";\n\n/**\n * Built-in HRMS plugin factory for @azlib/cms.\n * Equips the CMS engine with multi-tenant employers, employee profiles,\n * daily attendance check-in/out tracking, and leave quota approval workflows.\n */\nexport const hrmsPlugin = definePlugin<HRMSPluginOptions | void>(\n (options: HRMSPluginOptions | void): CMSPlugin => {\n const opts: HRMSPluginOptions = options || {};\n const collections = [createEmployeeCollection(opts)];\n\n if (opts.enableEmployers !== false) {\n collections.unshift(createEmployerCollection(opts));\n }\n\n if (opts.enableAttendance !== false) {\n collections.push(createAttendanceCollection(opts));\n }\n\n if (opts.enableLeaves !== false) {\n collections.push(createLeaveTypeCollection(opts));\n collections.push(createLeaveRequestCollection(opts));\n }\n\n const taxonomies = createHRMSTaxonomies(opts);\n\n return {\n name: \"hrms\",\n version: \"1.0.0\",\n description:\n \"Built-in Human Resource Management System (HRMS) plugin for employers, employees, attendance, and leave management\",\n collections,\n taxonomies,\n\n setup(ctx) {\n const service = new HRMSService(ctx.engine, opts);\n // Cache instance on engine for retrieval via getHRMSService\n (ctx.engine as any).__hrmsService = service;\n registerHRMSRoutes(ctx, service, opts);\n },\n };\n },\n);\n\n/**\n * Retrieve the active HRMSService instance associated with a CMSEngine.\n */\nexport function getHRMSService(\n engine: CMSEngine,\n options?: HRMSPluginOptions,\n): HRMSService {\n if ((engine as any).__hrmsService) {\n return (engine as any).__hrmsService;\n }\n const service = new HRMSService(engine, options);\n (engine as any).__hrmsService = service;\n return service;\n}\n","/**\n * @azlib/cms - Universal JSON Data Parser\n */\n\nexport function parseJsonSource(\n input: string | Uint8Array | Buffer | unknown,\n): Record<string, unknown>[] {\n if (Array.isArray(input)) {\n return input.filter((item): item is Record<string, unknown> =>\n Boolean(item && typeof item === \"object\" && !Array.isArray(item)),\n );\n }\n\n let text: string;\n if (typeof input === \"string\") {\n text = input.trim();\n } else if (input instanceof Uint8Array || Buffer.isBuffer(input)) {\n text = new TextDecoder(\"utf-8\").decode(input).trim();\n } else if (input && typeof input === \"object\") {\n const obj = input as Record<string, unknown>;\n if (Array.isArray(obj.data)) {\n return parseJsonSource(obj.data);\n }\n if (Array.isArray(obj.items)) {\n return parseJsonSource(obj.items);\n }\n return [obj];\n } else {\n throw new Error(\n \"[TransferParser] Invalid JSON input: expected string, buffer, or array.\",\n );\n }\n\n // Remove BOM if present\n if (text.charCodeAt(0) === 0xfeff) {\n text = text.slice(1);\n }\n\n if (!text) {\n return [];\n }\n\n // Try parsing as standard JSON\n try {\n const parsed = JSON.parse(text);\n if (Array.isArray(parsed)) {\n return parsed.filter((item): item is Record<string, unknown> =>\n Boolean(item && typeof item === \"object\" && !Array.isArray(item)),\n );\n }\n if (parsed && typeof parsed === \"object\") {\n if (Array.isArray(parsed.data)) {\n return parseJsonSource(parsed.data);\n }\n if (Array.isArray(parsed.items)) {\n return parseJsonSource(parsed.items);\n }\n return [parsed as Record<string, unknown>];\n }\n return [];\n } catch {\n // If standard JSON parsing fails, attempt line-delimited JSON (NDJSON)\n const lines = text\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .filter(Boolean);\n const records: Record<string, unknown>[] = [];\n for (const line of lines) {\n try {\n const item = JSON.parse(line);\n if (item && typeof item === \"object\" && !Array.isArray(item)) {\n records.push(item as Record<string, unknown>);\n }\n } catch (err) {\n throw new Error(\n `[TransferParser] Failed to parse JSON source: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n return records;\n }\n}\n","/**\n * @azlib/cms - Universal RFC 4180 CSV Data Parser\n */\n\nexport function parseCsvSource(\n input: string | Uint8Array | Buffer,\n): Record<string, unknown>[] {\n let text: string;\n if (typeof input === \"string\") {\n text = input;\n } else if (input instanceof Uint8Array || Buffer.isBuffer(input)) {\n text = new TextDecoder(\"utf-8\").decode(input);\n } else {\n throw new Error(\n \"[TransferParser] Invalid CSV input: expected string or buffer.\",\n );\n }\n\n // Strip BOM if present\n if (text.charCodeAt(0) === 0xfeff) {\n text = text.slice(1);\n }\n\n const rows = parseCsvRows(text);\n if (rows.length === 0) {\n return [];\n }\n\n // Extract headers from first non-empty row\n const rawHeaders = rows[0];\n const headers = rawHeaders.map((h, i) => {\n const trimmed = h.trim();\n return trimmed || `column_${i + 1}`;\n });\n\n const records: Record<string, unknown>[] = [];\n for (let r = 1; r < rows.length; r++) {\n const row = rows[r];\n // Skip completely empty rows\n if (row.length === 0 || (row.length === 1 && row[0].trim() === \"\")) {\n continue;\n }\n\n const record: Record<string, unknown> = {};\n for (let c = 0; c < headers.length; c++) {\n const header = headers[c];\n const val = c < row.length ? row[c].trim() : \"\";\n record[header] = coerceCsvValue(val);\n }\n records.push(record);\n }\n\n return records;\n}\n\n/**\n * Tokenize CSV into 2D array of string cells following RFC 4180.\n */\nfunction parseCsvRows(text: string): string[][] {\n const rows: string[][] = [];\n let currentRow: string[] = [];\n let currentCell = \"\";\n let insideQuotes = false;\n let i = 0;\n const len = text.length;\n\n while (i < len) {\n const char = text[i];\n\n if (insideQuotes) {\n if (char === '\"') {\n if (i + 1 < len && text[i + 1] === '\"') {\n // Escaped quote\n currentCell += '\"';\n i += 2;\n continue;\n } else {\n // Closing quote\n insideQuotes = false;\n i++;\n continue;\n }\n } else {\n currentCell += char;\n i++;\n continue;\n }\n }\n\n if (char === '\"') {\n insideQuotes = true;\n i++;\n continue;\n }\n\n if (char === \",\") {\n currentRow.push(currentCell);\n currentCell = \"\";\n i++;\n continue;\n }\n\n if (char === \"\\r\") {\n if (i + 1 < len && text[i + 1] === \"\\n\") {\n i++;\n }\n currentRow.push(currentCell);\n rows.push(currentRow);\n currentRow = [];\n currentCell = \"\";\n i++;\n continue;\n }\n\n if (char === \"\\n\") {\n currentRow.push(currentCell);\n rows.push(currentRow);\n currentRow = [];\n currentCell = \"\";\n i++;\n continue;\n }\n\n currentCell += char;\n i++;\n }\n\n // Flush remaining cell and row\n if (currentCell.length > 0 || currentRow.length > 0) {\n currentRow.push(currentCell);\n rows.push(currentRow);\n }\n\n return rows;\n}\n\n/**\n * Coerce obvious numeric / boolean CSV strings to primitives when lossless.\n */\nfunction coerceCsvValue(val: string): unknown {\n if (val === \"\") return \"\";\n if (val.toLowerCase() === \"true\") return true;\n if (val.toLowerCase() === \"false\") return false;\n if (val.toLowerCase() === \"null\") return null;\n\n // Check if standard integer or float (excluding strings with leading zeroes like postal codes or phone numbers)\n if (/^-?\\d+(\\.\\d+)?$/.test(val)) {\n if (val.length > 1 && val.startsWith(\"0\") && !val.startsWith(\"0.\")) {\n return val; // Preserve leading zero strings like \"0123\"\n }\n const num = Number(val);\n if (!Number.isNaN(num)) {\n return num;\n }\n }\n\n return val;\n}\n","/**\n * @azlib/cms - Universal Excel (.xlsx) Data Parser using ExcelJS\n */\n\nimport ExcelJS from \"exceljs\";\n\nexport interface ParseExcelResult {\n sheets: string[];\n selectedSheet: string;\n records: Record<string, unknown>[];\n}\n\nexport async function parseExcelSource(\n input: Buffer | Uint8Array | ArrayBuffer,\n options: { sheetName?: string } = {},\n): Promise<ParseExcelResult> {\n const workbook = new ExcelJS.Workbook();\n\n let buffer: Buffer;\n if (Buffer.isBuffer(input)) {\n buffer = input;\n } else if (input instanceof Uint8Array) {\n buffer = Buffer.from(input.buffer, input.byteOffset, input.byteLength);\n } else if (input instanceof ArrayBuffer) {\n buffer = Buffer.from(input);\n } else {\n throw new Error(\n \"[TransferParser] Invalid Excel input: expected Buffer, Uint8Array, or ArrayBuffer.\",\n );\n }\n\n await (workbook.xlsx.load as any)(buffer);\n\n const sheetNames = workbook.worksheets.map((s) => s.name);\n if (sheetNames.length === 0) {\n return {\n sheets: [],\n selectedSheet: \"\",\n records: [],\n };\n }\n\n let worksheet = options.sheetName\n ? workbook.getWorksheet(options.sheetName)\n : undefined;\n\n if (!worksheet) {\n worksheet = workbook.worksheets[0];\n }\n\n const selectedSheet = worksheet.name;\n const records: Record<string, unknown>[] = [];\n\n // Extract header row from row 1\n const headerRow = worksheet.getRow(1);\n const headers: string[] = [];\n\n headerRow.eachCell({ includeEmpty: false }, (cell, colNumber) => {\n let headerText = String(cell.value ?? \"\").trim();\n if (!headerText) {\n headerText = `column_${colNumber}`;\n }\n headers[colNumber] = headerText;\n });\n\n if (headers.length === 0) {\n return {\n sheets: sheetNames,\n selectedSheet,\n records: [],\n };\n }\n\n // Iterate over data rows starting from row 2\n const rowCount = worksheet.rowCount;\n for (let r = 2; r <= rowCount; r++) {\n const row = worksheet.getRow(r);\n // Check if row has any values\n let hasValues = false;\n const record: Record<string, unknown> = {};\n\n for (let c = 1; c < headers.length; c++) {\n const header = headers[c];\n if (!header) continue;\n\n const cell = row.getCell(c);\n const val = extractCellValue(cell.value);\n\n if (val !== undefined && val !== null && val !== \"\") {\n hasValues = true;\n }\n record[header] = val;\n }\n\n if (hasValues) {\n records.push(record);\n }\n }\n\n return {\n sheets: sheetNames,\n selectedSheet,\n records,\n };\n}\n\n/**\n * Normalizes ExcelJS cell values (handles formulas, dates, rich text, hyperlinks).\n */\nfunction extractCellValue(val: ExcelJS.CellValue): unknown {\n if (val === undefined || val === null) {\n return null;\n }\n\n // If Date object\n if (val instanceof Date) {\n return val.toISOString();\n }\n\n // If object\n if (typeof val === \"object\") {\n // Formula result\n if (\"formula\" in val) {\n const formulaVal = val as ExcelJS.CellFormulaValue;\n return extractCellValue(formulaVal.result as ExcelJS.CellValue);\n }\n // Hyperlink\n if (\"text\" in val && \"hyperlink\" in val) {\n return (val as ExcelJS.CellHyperlinkValue).text;\n }\n // Rich text\n if (\"richText\" in val && Array.isArray((val as any).richText)) {\n return (val as any).richText.map((t: any) => t.text).join(\"\");\n }\n // Error\n if (\"error\" in val) {\n return null;\n }\n }\n\n return val;\n}\n","/**\n * @azlib/cms - Universal Data Parser Dispatcher & Format Detector\n */\n\nimport type { SourceFormat } from \"../types.js\";\nimport { parseJsonSource } from \"./json.js\";\nimport { parseCsvSource } from \"./csv.js\";\nimport { parseExcelSource } from \"./excel.js\";\n\nexport interface ParseSourceOptions {\n format?: SourceFormat;\n fileName?: string;\n sheetName?: string;\n}\n\nexport interface ParsedSourceResult {\n format: SourceFormat;\n sheets?: string[];\n selectedSheet?: string;\n records: Record<string, unknown>[];\n}\n\n/**\n * Detect the format of an input payload if not explicitly provided.\n */\nexport function detectFormat(\n input: unknown,\n fileName?: string,\n): SourceFormat {\n if (Array.isArray(input)) {\n return \"json\";\n }\n\n if (fileName) {\n const lower = fileName.toLowerCase();\n if (lower.endsWith(\".xlsx\") || lower.endsWith(\".xls\")) return \"excel\";\n if (lower.endsWith(\".csv\")) return \"csv\";\n if (lower.endsWith(\".json\") || lower.endsWith(\".ndjson\")) return \"json\";\n }\n\n // Check binary signatures (Zip / XLSX starts with 0x50 0x4B 0x03 0x04)\n if (input instanceof Uint8Array || Buffer.isBuffer(input)) {\n if (\n input.length >= 4 &&\n input[0] === 0x50 &&\n input[1] === 0x4b &&\n input[2] === 0x03 &&\n input[3] === 0x04\n ) {\n return \"excel\";\n }\n // Try text decoding\n try {\n const head = new TextDecoder(\"utf-8\")\n .decode(input.slice(0, 100))\n .trim();\n if (head.startsWith(\"{\") || head.startsWith(\"[\")) return \"json\";\n if (head.includes(\",\") && head.includes(\"\\n\")) return \"csv\";\n } catch {\n // Fallback\n }\n }\n\n if (typeof input === \"string\") {\n const trimmed = input.trim();\n if (trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\")) {\n return \"json\";\n }\n if (trimmed.includes(\",\") || trimmed.includes(\"\\n\")) {\n return \"csv\";\n }\n }\n\n return \"json\";\n}\n\n/**\n * Universal source parser that handles JSON, CSV, and Excel (.xlsx).\n */\nexport async function parseSource(\n input: unknown,\n options: ParseSourceOptions = {},\n): Promise<ParsedSourceResult> {\n const format = options.format || detectFormat(input, options.fileName);\n\n switch (format) {\n case \"excel\": {\n const excelResult = await parseExcelSource(\n input as Buffer | Uint8Array | ArrayBuffer,\n { sheetName: options.sheetName },\n );\n return {\n format: \"excel\",\n sheets: excelResult.sheets,\n selectedSheet: excelResult.selectedSheet,\n records: excelResult.records,\n };\n }\n\n case \"csv\": {\n const records = parseCsvSource(input as string | Uint8Array | Buffer);\n return {\n format: \"csv\",\n records,\n };\n }\n\n case \"json\":\n default: {\n const records = parseJsonSource(input);\n return {\n format: \"json\",\n records,\n };\n }\n }\n}\n\nexport * from \"./json.js\";\nexport * from \"./csv.js\";\nexport * from \"./excel.js\";\n","/**\n * @azlib/cms - Universal JSON Serializer\n */\n\nexport interface SerializeJsonOptions {\n pretty?: boolean;\n}\n\nexport function serializeJson(\n records: Record<string, unknown>[],\n options: SerializeJsonOptions = {},\n): string {\n const indent = options.pretty !== false ? 2 : undefined;\n return JSON.stringify(records, null, indent);\n}\n","/**\n * @azlib/cms - Universal RFC 4180 CSV Serializer\n */\n\nexport interface SerializeCsvOptions {\n columns?: { key: string; header: string }[];\n}\n\nexport function serializeCsv(\n records: Record<string, unknown>[],\n options: SerializeCsvOptions = {},\n): string {\n if (records.length === 0) {\n return \"\";\n }\n\n // Derive column headers\n let columns = options.columns;\n if (!columns || columns.length === 0) {\n const keys = new Set<string>();\n for (const record of records) {\n for (const key of Object.keys(record)) {\n keys.add(key);\n }\n }\n columns = Array.from(keys).map((k) => ({ key: k, header: k }));\n }\n\n const lines: string[] = [];\n\n // Header line\n lines.push(columns.map((c) => escapeCsvCell(c.header)).join(\",\"));\n\n // Data lines\n for (const record of records) {\n const rowCells = columns.map((col) => {\n const val = record[col.key];\n return escapeCsvCell(formatCsvValue(val));\n });\n lines.push(rowCells.join(\",\"));\n }\n\n return lines.join(\"\\r\\n\");\n}\n\nfunction formatCsvValue(val: unknown): string {\n if (val === undefined || val === null) return \"\";\n if (typeof val === \"object\") {\n if (val instanceof Date) return val.toISOString();\n return JSON.stringify(val);\n }\n return String(val);\n}\n\nfunction escapeCsvCell(cell: string): string {\n if (\n cell.includes(\",\") ||\n cell.includes('\"') ||\n cell.includes(\"\\n\") ||\n cell.includes(\"\\r\")\n ) {\n return `\"${cell.replace(/\"/g, '\"\"')}\"`;\n }\n return cell;\n}\n","/**\n * @azlib/cms - Universal Excel (.xlsx) Serializer using ExcelJS\n */\n\nimport ExcelJS from \"exceljs\";\n\nexport interface SerializeExcelOptions {\n sheetName?: string;\n columns?: { key: string; header: string; width?: number }[];\n}\n\nexport async function serializeExcel(\n records: Record<string, unknown>[],\n options: SerializeExcelOptions = {},\n): Promise<Uint8Array> {\n const workbook = new ExcelJS.Workbook();\n const sheetName = (options.sheetName || \"Export\").replace(/[:\\\\/?*\\[\\]]/g, \"_\");\n const worksheet = workbook.addWorksheet(sheetName.slice(0, 31));\n\n // Determine columns\n let columns = options.columns;\n if (!columns || columns.length === 0) {\n const keys = new Set<string>();\n for (const record of records) {\n for (const key of Object.keys(record)) {\n keys.add(key);\n }\n }\n columns = Array.from(keys).map((k) => ({\n key: k,\n header: formatHeaderLabel(k),\n }));\n }\n\n // Calculate auto column widths\n worksheet.columns = columns.map((col) => {\n let maxLen = col.header.length;\n for (let i = 0; i < Math.min(records.length, 100); i++) {\n const val = records[i][col.key];\n if (val !== undefined && val !== null) {\n const str = typeof val === \"object\" ? JSON.stringify(val) : String(val);\n if (str.length > maxLen) {\n maxLen = Math.min(str.length, 50);\n }\n }\n }\n return {\n header: col.header,\n key: col.key,\n width: Math.max(maxLen + 4, col.width ?? 12),\n };\n });\n\n // Style header row\n const headerRow = worksheet.getRow(1);\n headerRow.height = 28;\n headerRow.eachCell((cell) => {\n cell.font = { bold: true, color: { argb: \"FF1E293B\" }, size: 11 };\n cell.fill = {\n type: \"pattern\",\n pattern: \"solid\",\n fgColor: { argb: \"FFF1F5F9\" },\n };\n cell.alignment = { vertical: \"middle\", horizontal: \"center\", wrapText: true };\n cell.border = {\n top: { style: \"thin\", color: { argb: \"FFE2E8F0\" } },\n bottom: { style: \"medium\", color: { argb: \"FFCBD5E1\" } },\n left: { style: \"thin\", color: { argb: \"FFE2E8F0\" } },\n right: { style: \"thin\", color: { argb: \"FFE2E8F0\" } },\n };\n });\n\n // Populate data rows\n for (const record of records) {\n const rowValues: Record<string, unknown> = {};\n for (const col of columns) {\n const val = record[col.key];\n rowValues[col.key] = formatExcelCellValue(val);\n }\n const row = worksheet.addRow(rowValues);\n row.height = 20;\n row.eachCell((cell) => {\n cell.alignment = { vertical: \"middle\" };\n cell.border = {\n top: { style: \"thin\", color: { argb: \"FFF1F5F9\" } },\n bottom: { style: \"thin\", color: { argb: \"FFF1F5F9\" } },\n left: { style: \"thin\", color: { argb: \"FFF1F5F9\" } },\n right: { style: \"thin\", color: { argb: \"FFF1F5F9\" } },\n };\n });\n }\n\n const arrayBuffer = await workbook.xlsx.writeBuffer();\n return new Uint8Array(arrayBuffer);\n}\n\nfunction formatHeaderLabel(key: string): string {\n // Convert camelCase or snake_case to Title Case\n return key\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .replace(/_/g, \" \")\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\nfunction formatExcelCellValue(val: unknown): unknown {\n if (val === undefined || val === null) {\n return \"\";\n }\n if (typeof val === \"number\" || typeof val === \"boolean\") {\n return val;\n }\n if (val instanceof Date) {\n return val;\n }\n if (typeof val === \"object\") {\n return JSON.stringify(val);\n }\n return String(val);\n}\n","/**\n * @azlib/cms - Universal Data Serializer Dispatcher\n */\n\nimport type { SourceFormat, TransferExportResult } from \"../types.js\";\nimport { serializeJson } from \"./json.js\";\nimport { serializeCsv } from \"./csv.js\";\nimport { serializeExcel } from \"./excel.js\";\n\nexport interface SerializeSourceOptions {\n format?: SourceFormat;\n fileName?: string;\n sheetName?: string;\n columns?: { key: string; header: string; width?: number }[];\n}\n\nexport async function serializeSource(\n records: Record<string, unknown>[],\n options: SerializeSourceOptions = {},\n): Promise<TransferExportResult> {\n const format = options.format || \"json\";\n const baseName = options.fileName || \"export\";\n\n switch (format) {\n case \"excel\": {\n const data = await serializeExcel(records, {\n sheetName: options.sheetName,\n columns: options.columns,\n });\n const fileName = baseName.endsWith(\".xlsx\")\n ? baseName\n : `${baseName}.xlsx`;\n return {\n format: \"excel\",\n data,\n mimeType:\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n fileName,\n totalRecords: records.length,\n };\n }\n\n case \"csv\": {\n const data = serializeCsv(records, {\n columns: options.columns,\n });\n const fileName = baseName.endsWith(\".csv\") ? baseName : `${baseName}.csv`;\n return {\n format: \"csv\",\n data,\n mimeType: \"text/csv; charset=utf-8\",\n fileName,\n totalRecords: records.length,\n };\n }\n\n case \"json\":\n default: {\n const data = serializeJson(records, { pretty: true });\n const fileName = baseName.endsWith(\".json\")\n ? baseName\n : `${baseName}.json`;\n return {\n format: \"json\",\n data,\n mimeType: \"application/json; charset=utf-8\",\n fileName,\n totalRecords: records.length,\n };\n }\n }\n}\n\nexport * from \"./json.js\";\nexport * from \"./csv.js\";\nexport * from \"./excel.js\";\n","/**\n * @azlib/cms - Universal Source File Schema Inspection & Field Auto-Matching\n */\n\nimport type { CollectionConfig } from \"../../core/types.js\";\nimport type {\n CollectionSchemaSummary,\n InferredFieldType,\n SourceFieldSchema,\n SourceFormat,\n SourceInspectionResult,\n SuggestedMappingRule,\n} from \"./types.js\";\nimport { parseSource, type ParseSourceOptions } from \"./parsers/index.js\";\n\nexport interface InspectOptions extends ParseSourceOptions {\n collectionConfig?: CollectionConfig;\n previewLimit?: number;\n}\n\n/**\n * Inspect an uploaded source file or payload to discover its schema,\n * infer column types, and generate auto-mapping suggestions against a target collection.\n */\nexport async function inspectSource(\n input: unknown,\n options: InspectOptions = {},\n): Promise<SourceInspectionResult> {\n const parsed = await parseSource(input, {\n format: options.format,\n fileName: options.fileName,\n sheetName: options.sheetName,\n });\n\n const records = parsed.records;\n const totalRows = records.length;\n const previewLimit = options.previewLimit ?? 5;\n const previewRows = records.slice(0, previewLimit);\n\n // Discover source fields\n const fieldKeys = new Set<string>();\n for (const row of records) {\n for (const key of Object.keys(row)) {\n fieldKeys.add(key);\n }\n }\n\n const sourceFields: SourceFieldSchema[] = [];\n for (const key of fieldKeys) {\n let nullCount = 0;\n const samples: unknown[] = [];\n const detectedTypes: InferredFieldType[] = [];\n\n for (const row of records) {\n const val = row[key];\n if (val === undefined || val === null || val === \"\") {\n nullCount++;\n } else {\n if (samples.length < 5) {\n samples.push(val);\n }\n detectedTypes.push(inferValueType(val));\n }\n }\n\n sourceFields.push({\n name: key,\n inferredType: resolveDominantType(detectedTypes),\n sampleValues: samples,\n nullCount,\n totalCount: totalRows,\n });\n }\n\n // Target schema summary if collection is supplied\n let targetSchema: CollectionSchemaSummary | undefined;\n let suggestedMapping: SuggestedMappingRule[] | undefined;\n\n if (options.collectionConfig) {\n targetSchema = summarizeCollection(options.collectionConfig);\n suggestedMapping = generateSuggestedMapping(\n sourceFields.map((f) => f.name),\n targetSchema,\n );\n }\n\n return {\n format: parsed.format,\n sheets: parsed.sheets,\n selectedSheet: parsed.selectedSheet,\n totalRows,\n sourceFields,\n targetSchema,\n suggestedMapping,\n previewRows,\n };\n}\n\n/**\n * Summarize a CMS CollectionConfig into consumer-friendly schema details.\n */\nexport function summarizeCollection(\n config: CollectionConfig,\n): CollectionSchemaSummary {\n return {\n slug: config.slug,\n label: config.label,\n singularLabel: config.singularLabel || config.label,\n description: config.description,\n taxonomies: config.taxonomies || [],\n fields: config.fields.map((f) => ({\n name: f.name,\n label: f.label || f.name,\n type: f.type,\n required: Boolean(f.required),\n unique: Boolean((f as any).unique),\n description: f.description,\n defaultValue: f.defaultValue,\n targetCollection: (f as any).targetCollection,\n options: (f as any).options,\n })),\n };\n}\n\n/**\n * Generates intelligent auto-mapping suggestions matching source headers to CMS fields.\n */\nexport function generateSuggestedMapping(\n sourceHeaders: string[],\n targetSchema: CollectionSchemaSummary,\n): SuggestedMappingRule[] {\n const suggestions: SuggestedMappingRule[] = [];\n const matchedTargets = new Set<string>();\n\n for (const sourceHeader of sourceHeaders) {\n let bestMatch: { field: string; confidence: number } | null = null;\n\n for (const targetField of targetSchema.fields) {\n if (matchedTargets.has(targetField.name)) {\n continue;\n }\n\n const score = calculateMatchConfidence(sourceHeader, targetField);\n if (score >= 0.6 && (!bestMatch || score > bestMatch.confidence)) {\n bestMatch = { field: targetField.name, confidence: score };\n }\n }\n\n if (bestMatch) {\n matchedTargets.add(bestMatch.field);\n suggestions.push({\n sourceField: sourceHeader,\n targetField: bestMatch.field,\n confidence: Number(bestMatch.confidence.toFixed(2)),\n });\n }\n }\n\n return suggestions;\n}\n\nfunction normalize(str: string): string {\n return str\n .toLowerCase()\n .replace(/[^a-z0-9]/g, \"\");\n}\n\n/**\n * Common field synonyms dictionary for intuitive fuzzy matching.\n */\nconst SYNONYMS: Record<string, string[]> = {\n employeeNumber: [\"empid\", \"employeeid\", \"empnumber\", \"staffid\", \"badgenumber\", \"staffno\", \"empno\"],\n companyName: [\"company\", \"organization\", \"employer\", \"businessname\", \"employername\", \"firm\"],\n firstName: [\"fname\", \"givenname\", \"first\"],\n lastName: [\"lname\", \"surname\", \"familyname\", \"last\"],\n email: [\"mail\", \"workemail\", \"primaryemail\", \"emailaddress\"],\n phone: [\"mobile\", \"cell\", \"telephone\", \"phonenumber\", \"contactnumber\", \"tel\"],\n employerId: [\"employer\", \"companyid\", \"company\", \"organizationid\", \"orgid\"],\n hireDate: [\"startdate\", \"joiningdate\", \"hired\", \"dateofjoining\"],\n jobTitle: [\"title\", \"position\", \"role\", \"designation\"],\n employmentType: [\"contracttype\", \"worktype\", \"jobtype\"],\n salary: [\"compensation\", \"wage\", \"pay\", \"rate\", \"annualsalary\"],\n taxId: [\"ein\", \"vat\", \"taxnumber\", \"tin\"],\n status: [\"state\", \"active\"],\n};\n\nfunction calculateMatchConfidence(\n sourceHeader: string,\n targetField: { name: string; label: string },\n): number {\n const normSource = normalize(sourceHeader);\n const normTargetName = normalize(targetField.name);\n const normTargetLabel = normalize(targetField.label);\n\n // 1. Exact match on field name\n if (sourceHeader === targetField.name) return 1.0;\n if (normSource === normTargetName) return 0.95;\n\n // 2. Exact match on human label\n if (sourceHeader.toLowerCase() === targetField.label.toLowerCase()) return 0.92;\n if (normSource === normTargetLabel) return 0.9;\n\n // 3. Synonym match\n const synonyms = SYNONYMS[targetField.name];\n if (synonyms && synonyms.includes(normSource)) {\n return 0.85;\n }\n\n // 4. Substring / contains match\n if (normSource.includes(normTargetName) || normTargetName.includes(normSource)) {\n return 0.7;\n }\n if (normSource.includes(normTargetLabel) || normTargetLabel.includes(normSource)) {\n return 0.65;\n }\n\n return 0.0;\n}\n\nfunction inferValueType(val: unknown): InferredFieldType {\n if (typeof val === \"boolean\") return \"boolean\";\n if (typeof val === \"number\") return \"number\";\n if (Array.isArray(val)) return \"array\";\n if (val && typeof val === \"object\") return \"object\";\n\n if (typeof val === \"string\") {\n const s = val.trim();\n if (s.toLowerCase() === \"true\" || s.toLowerCase() === \"false\") {\n return \"boolean\";\n }\n // Check if numeric\n if (/^-?\\d+(\\.\\d+)?$/.test(s) && !/^0\\d+/.test(s)) {\n return \"number\";\n }\n // Check if ISO / standard date string (e.g. 2024-01-15 or 2024-01-15T00:00:00Z)\n if (/^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?(Z|[+-]\\d{2}:?\\d{2})?)?$/.test(s)) {\n const parsed = Date.parse(s);\n if (!Number.isNaN(parsed)) {\n return \"date\";\n }\n }\n }\n\n return \"string\";\n}\n\nfunction resolveDominantType(types: InferredFieldType[]): InferredFieldType {\n if (types.length === 0) return \"string\";\n\n const counts = new Map<InferredFieldType, number>();\n for (const t of types) {\n counts.set(t, (counts.get(t) || 0) + 1);\n }\n\n let dominant: InferredFieldType = \"string\";\n let maxCount = 0;\n for (const [t, count] of counts) {\n if (count > maxCount) {\n maxCount = count;\n dominant = t;\n }\n }\n\n return dominant;\n}\n","/**\n * @azlib/cms - Universal Data Definition Mapping & Transformation Engine\n */\n\nimport type { ContentItem } from \"../../core/types.js\";\nimport { slugify } from \"../../content/slug.js\";\nimport type {\n DataMappingDefinition,\n FieldMappingRule,\n FieldTransformPreset,\n} from \"./types.js\";\n\n/**\n * Apply a mapping definition to transform an external raw record into a CMS content payload.\n */\nexport function mapSourceRecord(\n rawRecord: Record<string, unknown>,\n mapping: DataMappingDefinition,\n): { data: Record<string, unknown>; title?: string; slug?: string; status?: string } {\n const mappedData: Record<string, unknown> = {};\n const mappedTargetFields = new Set<string>();\n\n for (const rule of mapping.fields) {\n mappedTargetFields.add(rule.targetField);\n const sourceVal = rawRecord[rule.sourceField];\n const transformed = applyFieldTransform(rule, sourceVal, rawRecord);\n\n if (transformed !== undefined) {\n mappedData[rule.targetField] = transformed;\n }\n }\n\n // Preserve unmapped fields if requested\n if (mapping.options?.ignoreUnmappedFields === false) {\n for (const [key, val] of Object.entries(rawRecord)) {\n if (!mapping.fields.some((r) => r.sourceField === key)) {\n mappedData[key] = val;\n }\n }\n }\n\n // Resolve standard CMS top-level fields\n let title: string | undefined = typeof mappedData.title === \"string\" ? mappedData.title : undefined;\n if (!title) {\n if (typeof mappedData.companyName === \"string\") {\n title = mappedData.companyName;\n } else if (typeof mappedData.name === \"string\") {\n title = mappedData.name;\n } else if (\n typeof mappedData.firstName === \"string\" ||\n typeof mappedData.lastName === \"string\"\n ) {\n const parts = [mappedData.firstName, mappedData.lastName].filter(Boolean);\n if (parts.length > 0) title = parts.join(\" \");\n }\n }\n\n let slug: string | undefined = typeof mappedData.slug === \"string\" ? mappedData.slug : undefined;\n if (!slug && mapping.options?.autoGenerateSlug !== false && title) {\n slug = slugify(title);\n }\n\n let status: string | undefined = mapping.options?.defaultStatus;\n if (mapping.options?.statusField && mappedData[mapping.options.statusField]) {\n status = String(mappedData[mapping.options.statusField]);\n }\n\n return { data: mappedData, title, slug, status };\n}\n\n/**\n * Applies transform preset or custom function to a field value.\n */\nexport function applyFieldTransform(\n rule: FieldMappingRule,\n value: unknown,\n rawRecord: Record<string, unknown>,\n): unknown {\n let val = value;\n\n // Custom callback transform\n if (typeof rule.transform === \"function\") {\n try {\n val = rule.transform(val, rawRecord);\n } catch (err) {\n throw new Error(\n `Transform error on field '${rule.sourceField}': ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n } else if (rule.transform && typeof rule.transform === \"string\") {\n val = applyPresetTransform(rule.transform, val);\n }\n\n // Apply default fallback if null or undefined or empty string\n if (val === undefined || val === null || val === \"\") {\n if (rule.defaultValue !== undefined) {\n val = rule.defaultValue;\n }\n }\n\n return val;\n}\n\nfunction applyPresetTransform(preset: FieldTransformPreset, val: unknown): unknown {\n if (val === undefined || val === null) return val;\n\n switch (preset) {\n case \"trim\":\n return typeof val === \"string\" ? val.trim() : val;\n\n case \"lowercase\":\n return typeof val === \"string\" ? val.toLowerCase() : val;\n\n case \"uppercase\":\n return typeof val === \"string\" ? val.toUpperCase() : val;\n\n case \"number\": {\n if (typeof val === \"number\") return val;\n const parsed = Number(val);\n return Number.isNaN(parsed) ? val : parsed;\n }\n\n case \"boolean\": {\n if (typeof val === \"boolean\") return val;\n const s = String(val).toLowerCase().trim();\n if (s === \"true\" || s === \"1\" || s === \"yes\") return true;\n if (s === \"false\" || s === \"0\" || s === \"no\") return false;\n return Boolean(val);\n }\n\n case \"date\": {\n if (val instanceof Date) return val.toISOString();\n const s = String(val).trim();\n const parsed = Date.parse(s);\n return Number.isNaN(parsed) ? s : new Date(parsed).toISOString();\n }\n\n case \"json\": {\n if (typeof val === \"object\") return val;\n try {\n return JSON.parse(String(val));\n } catch {\n return val;\n }\n }\n\n case \"slug\":\n return slugify(String(val));\n\n case \"split_comma\": {\n if (Array.isArray(val)) return val;\n return String(val)\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n }\n\n case \"identity\":\n default:\n return val;\n }\n}\n\n/**\n * Reverse mapping for export: transforms a CMS ContentItem into an external export record.\n */\nexport function mapCmsItemForExport(\n item: ContentItem<Record<string, unknown>>,\n mapping?: DataMappingDefinition,\n options: { includeId?: boolean; includeTimestamps?: boolean } = {},\n): Record<string, unknown> {\n const exportRecord: Record<string, unknown> = {};\n\n // Custom mapping definition applied in reverse\n if (mapping && mapping.fields.length > 0) {\n for (const rule of mapping.fields) {\n // Look up targetField in item.data or top-level item\n const val =\n item.data[rule.targetField] !== undefined\n ? item.data[rule.targetField]\n : (item as any)[rule.targetField];\n\n exportRecord[rule.sourceField] = val !== undefined ? val : (rule.defaultValue ?? \"\");\n }\n return exportRecord;\n }\n\n // Default projection\n if (options.includeId !== false) {\n exportRecord.id = item.id;\n }\n if (item.title) exportRecord.title = item.title;\n if (item.slug) exportRecord.slug = item.slug;\n if (item.status) exportRecord.status = item.status;\n\n // Append custom data fields\n for (const [k, v] of Object.entries(item.data)) {\n exportRecord[k] = v;\n }\n\n if (options.includeTimestamps) {\n exportRecord.createdAt = item.createdAt;\n exportRecord.updatedAt = item.updatedAt;\n }\n\n return exportRecord;\n}\n","/**\n * @azlib/cms - Universal Multi-Tiered Data Validation & Constraint Engine\n */\n\nimport type { CollectionConfig, FieldDefinition } from \"../../core/types.js\";\nimport type { CMSStorageAdapter } from \"../../storage/storage-contract.js\";\nimport type {\n DataMappingDefinition,\n TransferErrorDetail,\n ValidationPreviewRow,\n ValidationResult,\n} from \"./types.js\";\nimport { mapSourceRecord } from \"./mapping.js\";\n\nexport interface ValidateTransferOptions {\n storage?: CMSStorageAdapter;\n onDuplicate?: \"error\" | \"update\" | \"skip\";\n previewLimit?: number;\n}\n\n/**\n * Validates a batch of source records against a target CMS collection configuration\n * and live database constraints.\n */\nexport async function validateTransferBatch(\n rawRecords: Record<string, unknown>[],\n mapping: DataMappingDefinition,\n collectionConfig: CollectionConfig,\n options: ValidateTransferOptions = {},\n): Promise<ValidationResult> {\n const errors: TransferErrorDetail[] = [];\n const previewRows: ValidationPreviewRow[] = [];\n const previewLimit = options.previewLimit ?? 10;\n const onDuplicate = options.onDuplicate ?? mapping.options?.onDuplicate ?? \"error\";\n\n // Identify unique fields and relationship fields\n const uniqueFields = collectionConfig.fields.filter(\n (f) => Boolean((f as any).unique) || f.name === \"slug\",\n );\n const relationshipFields = collectionConfig.fields.filter(\n (f) => f.type === \"relationship\" && Boolean((f as any).targetCollection),\n );\n\n // Track intra-batch values for unique constraint detection\n const seenUniqueValues = new Map<string, Map<unknown, number>>();\n for (const uf of uniqueFields) {\n seenUniqueValues.set(uf.name, new Map());\n }\n\n let validCount = 0;\n\n for (let i = 0; i < rawRecords.length; i++) {\n const rowNumber = i + 1;\n const raw = rawRecords[i];\n const rowErrors: TransferErrorDetail[] = [];\n\n // 1. Mapping & Transform Phase\n let mappedResult: {\n data: Record<string, unknown>;\n title?: string;\n slug?: string;\n status?: string;\n };\n\n try {\n mappedResult = mapSourceRecord(raw, mapping);\n } catch (err: unknown) {\n const errDetail: TransferErrorDetail = {\n rowNumber,\n code: \"TRANSFORM_ERROR\",\n reason: err instanceof Error ? err.message : String(err),\n };\n rowErrors.push(errDetail);\n errors.push(errDetail);\n if (previewRows.length < previewLimit) {\n previewRows.push({\n rowNumber,\n raw,\n mapped: {},\n valid: false,\n errors: rowErrors,\n });\n }\n continue;\n }\n\n const data = mappedResult.data;\n\n // 2. Field Schema Level Validation\n for (const field of collectionConfig.fields) {\n validateField(field, data, rowNumber, rowErrors);\n }\n\n // Required check for mapping rules marked required\n for (const rule of mapping.fields) {\n if (rule.required && !collectionConfig.fields.some((f) => f.name === rule.targetField)) {\n const val = data[rule.targetField];\n if (val === undefined || val === null || val === \"\") {\n rowErrors.push({\n rowNumber,\n field: rule.targetField,\n value: val,\n code: \"REQUIRED_FIELD_MISSING\",\n reason: `Field '${rule.targetField}' is required by mapping definition.`,\n });\n }\n }\n }\n\n // 3. Database Constraints Validation (Uniqueness & Relationships)\n for (const uf of uniqueFields) {\n const val = data[uf.name] ?? (uf.name === \"slug\" ? mappedResult.slug : undefined);\n if (val !== undefined && val !== null && val !== \"\") {\n // Intra-batch unique check\n const seenMap = seenUniqueValues.get(uf.name)!;\n if (seenMap.has(val)) {\n const prevRow = seenMap.get(val)!;\n rowErrors.push({\n rowNumber,\n field: uf.name,\n value: val,\n code: \"CONSTRAINT_UNIQUE_VIOLATION\",\n reason: `${uf.label || uf.name} value '${val}' is duplicated in row ${prevRow} and row ${rowNumber}.`,\n });\n } else {\n seenMap.set(val, rowNumber);\n }\n\n // Live database unique check if storage adapter is available\n if (options.storage && onDuplicate === \"error\") {\n const exists = await checkExistingUnique(\n options.storage,\n collectionConfig.slug,\n uf.name,\n val,\n );\n if (exists) {\n rowErrors.push({\n rowNumber,\n field: uf.name,\n value: val,\n code: \"CONSTRAINT_UNIQUE_VIOLATION\",\n reason: `${uf.label || uf.name} value '${val}' already exists in database.`,\n });\n }\n }\n }\n }\n\n // Foreign key / relationship check\n if (options.storage) {\n for (const rf of relationshipFields) {\n const targetColl = (rf as any).targetCollection as string;\n const refVal = data[rf.name];\n if (refVal !== undefined && refVal !== null && refVal !== \"\") {\n const exists = await checkRelationshipExists(\n options.storage,\n targetColl,\n refVal,\n );\n if (!exists) {\n rowErrors.push({\n rowNumber,\n field: rf.name,\n value: refVal,\n code: \"CONSTRAINT_FOREIGN_KEY_VIOLATION\",\n reason: `Referenced ${rf.label || rf.name} with identifier '${refVal}' does not exist in collection '${targetColl}'.`,\n });\n }\n }\n }\n }\n\n if (rowErrors.length === 0) {\n validCount++;\n } else {\n errors.push(...rowErrors);\n }\n\n if (previewRows.length < previewLimit) {\n previewRows.push({\n rowNumber,\n raw,\n mapped: data,\n valid: rowErrors.length === 0,\n errors: rowErrors.length > 0 ? rowErrors : undefined,\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n totalRows: rawRecords.length,\n validCount,\n errorCount: errors.length,\n errors,\n previewRows,\n };\n}\n\n/**\n * Validates a single field against its FieldDefinition.\n */\nfunction validateField(\n field: FieldDefinition,\n data: Record<string, unknown>,\n rowNumber: number,\n errors: TransferErrorDetail[],\n): void {\n const val = data[field.name];\n const label = field.label || field.name;\n\n // 1. Required check\n if (field.required && (val === undefined || val === null || val === \"\")) {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"REQUIRED_FIELD_MISSING\",\n reason: `${label} is required.`,\n });\n return;\n }\n\n if (val === undefined || val === null || val === \"\") {\n return;\n }\n\n // 2. Data Type validation\n switch (field.type) {\n case \"number\": {\n const num = typeof val === \"number\" ? val : Number(val);\n if (Number.isNaN(num)) {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"INVALID_DATA_TYPE\",\n reason: `${label} must be a valid number, received '${val}'.`,\n });\n } else {\n data[field.name] = num;\n // Min / Max constraint\n const min = (field as any).min as number | undefined;\n const max = (field as any).max as number | undefined;\n if (min !== undefined && num < min) {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"VALIDATION_RULE_FAILED\",\n reason: `${label} must be greater than or equal to ${min}.`,\n });\n }\n if (max !== undefined && num > max) {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"VALIDATION_RULE_FAILED\",\n reason: `${label} must be less than or equal to ${max}.`,\n });\n }\n }\n break;\n }\n\n case \"boolean\": {\n if (typeof val !== \"boolean\") {\n const s = String(val).toLowerCase().trim();\n if (s === \"true\" || s === \"1\" || s === \"yes\") {\n data[field.name] = true;\n } else if (s === \"false\" || s === \"0\" || s === \"no\") {\n data[field.name] = false;\n } else {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"INVALID_DATA_TYPE\",\n reason: `${label} must be a boolean (true/false), received '${val}'.`,\n });\n }\n }\n break;\n }\n\n case \"date\": {\n const parsed = Date.parse(String(val));\n if (Number.isNaN(parsed)) {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"INVALID_DATA_TYPE\",\n reason: `${label} must be a valid date, received '${val}'.`,\n });\n }\n break;\n }\n\n case \"select\": {\n const options = (field as any).options as readonly (\n | string\n | { label: string; value: string | number }\n )[];\n if (options && options.length > 0) {\n const allowedValues = options.map((opt) =>\n typeof opt === \"object\" ? String(opt.value) : String(opt),\n );\n if (!allowedValues.includes(String(val))) {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"INVALID_SELECT_OPTION\",\n reason: `${label} value '${val}' is not a valid option (allowed: ${allowedValues.join(\", \")}).`,\n });\n }\n }\n break;\n }\n\n case \"json\": {\n if (typeof val === \"string\") {\n try {\n data[field.name] = JSON.parse(val);\n } catch {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"INVALID_DATA_TYPE\",\n reason: `${label} must be a valid JSON structure.`,\n });\n }\n }\n break;\n }\n }\n\n // 3. Custom Field Validator\n if (typeof (field as any).validate === \"function\") {\n try {\n const res = (field as any).validate(val, data);\n if (typeof res === \"string\") {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"VALIDATION_RULE_FAILED\",\n reason: res,\n });\n } else if (res === false) {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"VALIDATION_RULE_FAILED\",\n reason: `${label} failed custom validation constraint.`,\n });\n }\n } catch (err: unknown) {\n errors.push({\n rowNumber,\n field: field.name,\n value: val,\n code: \"VALIDATION_RULE_FAILED\",\n reason: err instanceof Error ? err.message : String(err),\n });\n }\n }\n}\n\nasync function checkExistingUnique(\n storage: CMSStorageAdapter,\n collectionSlug: string,\n fieldName: string,\n value: unknown,\n): Promise<boolean> {\n if (fieldName === \"slug\") {\n const item = await storage.getContentBySlug(collectionSlug, String(value));\n return item !== null;\n }\n const result = await storage.findContent(collectionSlug, {\n where: { [fieldName]: value },\n limit: 1,\n });\n return result.items.length > 0;\n}\n\nasync function checkRelationshipExists(\n storage: CMSStorageAdapter,\n targetCollection: string,\n refId: unknown,\n): Promise<boolean> {\n const idStr = String(refId);\n const byId = await storage.getContent(targetCollection, idStr);\n if (byId !== null) return true;\n\n const bySlug = await storage.getContentBySlug(targetCollection, idStr);\n return bySlug !== null;\n}\n","/**\n * @azlib/cms - Built-in HRMS Data Transfer Mapping Presets\n */\n\nimport type { DataMappingDefinition } from \"../types.js\";\n\n/**\n * Preconfigured mapping definition for importing and exporting HRMS Employers.\n */\nexport const HRMS_EMPLOYER_TRANSFER_PRESET: DataMappingDefinition = {\n id: \"hrms_employers_preset\",\n name: \"HRMS Employers Standard Mapping\",\n collectionSlug: \"employers\",\n fields: [\n { sourceField: \"Company Name\", targetField: \"companyName\", required: true },\n { sourceField: \"Legal Name\", targetField: \"legalName\" },\n { sourceField: \"Tax ID\", targetField: \"taxId\" },\n { sourceField: \"Primary Email\", targetField: \"email\", transform: \"trim\" },\n { sourceField: \"Phone\", targetField: \"phone\", transform: \"trim\" },\n { sourceField: \"Website\", targetField: \"website\" },\n { sourceField: \"Timezone\", targetField: \"timezone\", defaultValue: \"UTC\" },\n { sourceField: \"Status\", targetField: \"status\", defaultValue: \"active\" },\n ],\n options: {\n autoGenerateSlug: true,\n defaultStatus: \"published\",\n onDuplicate: \"update\",\n uniqueIdentifierField: \"taxId\",\n },\n};\n\n/**\n * Preconfigured mapping definition for importing and exporting HRMS Employees.\n */\nexport const HRMS_EMPLOYEE_TRANSFER_PRESET: DataMappingDefinition = {\n id: \"hrms_employees_preset\",\n name: \"HRMS Employees Standard Mapping\",\n collectionSlug: \"employees\",\n fields: [\n {\n sourceField: \"Employer ID\",\n targetField: \"employerId\",\n required: true,\n },\n {\n sourceField: \"Employee Number\",\n targetField: \"employeeNumber\",\n required: true,\n transform: \"trim\",\n },\n {\n sourceField: \"First Name\",\n targetField: \"firstName\",\n required: true,\n transform: \"trim\",\n },\n {\n sourceField: \"Last Name\",\n targetField: \"lastName\",\n required: true,\n transform: \"trim\",\n },\n {\n sourceField: \"Work Email\",\n targetField: \"email\",\n required: true,\n transform: \"lowercase\",\n },\n {\n sourceField: \"Phone\",\n targetField: \"phone\",\n transform: \"trim\",\n },\n {\n sourceField: \"Job Title\",\n targetField: \"jobTitle\",\n },\n {\n sourceField: \"Employment Type\",\n targetField: \"employmentType\",\n defaultValue: \"full_time\",\n },\n {\n sourceField: \"Hire Date\",\n targetField: \"hireDate\",\n required: true,\n transform: \"date\",\n },\n {\n sourceField: \"Status\",\n targetField: \"status\",\n defaultValue: \"active\",\n },\n ],\n options: {\n autoGenerateSlug: true,\n defaultStatus: \"published\",\n onDuplicate: \"error\",\n uniqueIdentifierField: \"employeeNumber\",\n },\n};\n","/**\n * @azlib/cms - Universal Transfer Service Engine\n */\n\nimport type { CMSEngine } from \"../../core/engine.js\";\nimport type { CollectionConfig, ContentItem } from \"../../core/types.js\";\nimport type {\n CollectionSchemaSummary,\n DataMappingDefinition,\n SourceFormat,\n SourceInspectionResult,\n TransferErrorDetail,\n TransferExportOptions,\n TransferExportResult,\n TransferImportOptions,\n TransferImportResult,\n TransferPluginOptions,\n ValidationResult,\n} from \"./types.js\";\nimport { parseSource, type ParseSourceOptions } from \"./parsers/index.js\";\nimport { serializeSource } from \"./serializers/index.js\";\nimport { inspectSource, summarizeCollection } from \"./inspect.js\";\nimport { mapCmsItemForExport, mapSourceRecord } from \"./mapping.js\";\nimport { validateTransferBatch } from \"./validator.js\";\nimport {\n HRMS_EMPLOYEE_TRANSFER_PRESET,\n HRMS_EMPLOYER_TRANSFER_PRESET,\n} from \"./presets/hrms.js\";\n\nexport class TransferService {\n private presets = new Map<string, DataMappingDefinition>();\n\n constructor(\n public readonly engine: CMSEngine,\n public readonly options: TransferPluginOptions = {},\n ) {\n // Register built-in presets\n this.registerPreset(HRMS_EMPLOYER_TRANSFER_PRESET);\n this.registerPreset(HRMS_EMPLOYEE_TRANSFER_PRESET);\n }\n\n /**\n * List all registered collections across all active plugins in the engine.\n */\n listCollections(): CollectionSchemaSummary[] {\n return this.engine.getCollections().map(summarizeCollection);\n }\n\n /**\n * Get the collection schema summary for a specific collection slug.\n */\n getCollectionSchema(collectionSlug: string): CollectionSchemaSummary {\n const config = this.getCollectionConfigOrThrow(collectionSlug);\n return summarizeCollection(config);\n }\n\n /**\n * Register a reusable data mapping preset.\n */\n registerPreset(preset: DataMappingDefinition): void {\n const id = preset.id || `${preset.collectionSlug}_${preset.name || \"preset\"}`;\n this.presets.set(id, { ...preset, id });\n }\n\n /**\n * Get a registered preset by ID.\n */\n getPreset(id: string): DataMappingDefinition | undefined {\n return this.presets.get(id);\n }\n\n /**\n * Get all registered presets, optionally filtered by target collection.\n */\n getPresets(collectionSlug?: string): DataMappingDefinition[] {\n const all = Array.from(this.presets.values());\n if (collectionSlug) {\n return all.filter((p) => p.collectionSlug === collectionSlug);\n }\n return all;\n }\n\n /**\n * Generate a 1:1 default mapping template for any collection.\n */\n getMappingTemplate(collectionSlug: string): DataMappingDefinition {\n const config = this.getCollectionConfigOrThrow(collectionSlug);\n return {\n id: `${collectionSlug}_default_template`,\n name: `${config.label} Default Template`,\n collectionSlug,\n fields: config.fields.map((f) => ({\n sourceField: f.name,\n targetField: f.name,\n required: Boolean(f.required),\n defaultValue: f.defaultValue,\n })),\n options: {\n autoGenerateSlug: true,\n defaultStatus: config.draftable ? \"draft\" : \"published\",\n onDuplicate: \"error\",\n },\n };\n }\n\n /**\n * Inspect any source payload or file (JSON, Excel, CSV) to extract headers,\n * infer data types, and generate auto-mapping suggestions against a target collection.\n */\n async inspectSource(\n input: unknown,\n options: ParseSourceOptions & { collectionSlug?: string; previewLimit?: number } = {},\n ): Promise<SourceInspectionResult> {\n const config = options.collectionSlug\n ? this.engine.getCollectionConfig(options.collectionSlug)\n : undefined;\n\n return inspectSource(input, {\n ...options,\n collectionConfig: config,\n });\n }\n\n /**\n * Dry-run validation of a source batch against a target collection's schema\n * and live database constraints without committing any changes.\n */\n async validateImport(\n collectionSlug: string,\n input: unknown,\n mapping?: DataMappingDefinition,\n options: ParseSourceOptions & {\n onDuplicate?: \"error\" | \"update\" | \"skip\";\n previewLimit?: number;\n } = {},\n ): Promise<ValidationResult> {\n const config = this.getCollectionConfigOrThrow(collectionSlug);\n const parsed = await parseSource(input, {\n format: options.format,\n fileName: options.fileName,\n sheetName: options.sheetName,\n });\n\n const activeMapping = mapping || this.getMappingTemplate(collectionSlug);\n\n return validateTransferBatch(parsed.records, activeMapping, config, {\n storage: this.engine.storage,\n onDuplicate: options.onDuplicate,\n previewLimit: options.previewLimit,\n });\n }\n\n /**\n * Execute an import batch from raw data or an external file (JSON, Excel, CSV)\n * into a target CMS collection.\n */\n async importData(\n collectionSlug: string,\n input: unknown,\n mapping?: DataMappingDefinition,\n options: TransferImportOptions & ParseSourceOptions = {},\n ): Promise<TransferImportResult> {\n const config = this.getCollectionConfigOrThrow(collectionSlug);\n const parsed = await parseSource(input, {\n format: options.format,\n fileName: options.fileName,\n sheetName: options.sheetName,\n });\n\n const activeMapping = mapping || this.getMappingTemplate(collectionSlug);\n const rawRecords = parsed.records;\n const onDuplicate = options.onDuplicate ?? activeMapping.options?.onDuplicate ?? \"error\";\n const abortOnError = options.abortOnError ?? activeMapping.options?.abortOnError ?? false;\n\n // Run pre-import validation\n const validation = await validateTransferBatch(\n rawRecords,\n activeMapping,\n config,\n {\n storage: this.engine.storage,\n onDuplicate,\n },\n );\n\n // If dry run requested, return results without creating records\n if (options.dryRun) {\n return {\n success: validation.valid,\n collectionSlug,\n totalRows: rawRecords.length,\n importedCount: validation.validCount,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: validation.errorCount,\n createdIds: [],\n updatedIds: [],\n errors: validation.errors,\n };\n }\n\n if (abortOnError && !validation.valid) {\n return {\n success: false,\n collectionSlug,\n totalRows: rawRecords.length,\n importedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: validation.errorCount,\n createdIds: [],\n updatedIds: [],\n errors: validation.errors,\n };\n }\n\n await this.engine.hooks.doAction(\"cms.transfer_import_started\", {\n collectionSlug,\n totalRows: rawRecords.length,\n });\n\n const createdIds: string[] = [];\n const updatedIds: string[] = [];\n const errors: TransferErrorDetail[] = [...validation.errors];\n let importedCount = 0;\n let updatedCount = 0;\n let skippedCount = 0;\n\n // Map row index to errors\n const rowErrorsMap = new Map<number, TransferErrorDetail[]>();\n for (const err of validation.errors) {\n const list = rowErrorsMap.get(err.rowNumber) || [];\n list.push(err);\n rowErrorsMap.set(err.rowNumber, list);\n }\n\n const collService = this.engine.collection(collectionSlug);\n\n for (let i = 0; i < rawRecords.length; i++) {\n const rowNumber = i + 1;\n const rowErrors = rowErrorsMap.get(rowNumber);\n\n // Check if row had non-duplicate errors (or unique error when onDuplicate === 'error')\n if (rowErrors && rowErrors.length > 0) {\n const hasFatalError = rowErrors.some(\n (e) => e.code !== \"CONSTRAINT_UNIQUE_VIOLATION\" || onDuplicate === \"error\",\n );\n if (hasFatalError) {\n continue;\n }\n }\n\n const raw = rawRecords[i];\n let mapped: {\n data: Record<string, unknown>;\n title?: string;\n slug?: string;\n status?: string;\n };\n\n try {\n mapped = mapSourceRecord(raw, activeMapping);\n } catch (err: unknown) {\n errors.push({\n rowNumber,\n code: \"TRANSFORM_ERROR\",\n reason: err instanceof Error ? err.message : String(err),\n });\n continue;\n }\n\n // Filter hook allowing plugins to enrich or transform row before saving\n mapped = await this.engine.hooks.applyFilters(\n \"cms.transfer_before_import_row\",\n mapped,\n { collectionSlug, rowNumber, raw },\n );\n\n // Handle duplicate resolution\n const identifierField =\n options.uniqueIdentifierField ||\n activeMapping.options?.uniqueIdentifierField ||\n this.detectUniqueField(config);\n\n let existingItem: ContentItem | null = null;\n\n if (identifierField && mapped.data[identifierField] !== undefined) {\n const val = mapped.data[identifierField];\n if (identifierField === \"slug\") {\n existingItem = await this.engine.storage.getContentBySlug(collectionSlug, String(val));\n } else {\n const res = await this.engine.storage.findContent(collectionSlug, {\n where: { [identifierField]: val },\n limit: 1,\n });\n existingItem = res.items[0] || null;\n }\n }\n\n if (existingItem) {\n if (onDuplicate === \"skip\") {\n skippedCount++;\n continue;\n }\n\n if (onDuplicate === \"update\") {\n try {\n const updated = await collService.update(\n existingItem.id,\n {\n title: mapped.title ?? existingItem.title,\n slug: mapped.slug ?? existingItem.slug,\n status: (mapped.status as any) ?? existingItem.status,\n data: { ...existingItem.data, ...mapped.data },\n },\n options.authorId,\n options.revisionNote || \"Import transfer update\",\n );\n if (updated) {\n updatedIds.push(updated.id);\n updatedCount++;\n await this.engine.hooks.doAction(\"cms.transfer_row_imported\", {\n collectionSlug,\n action: \"update\",\n item: updated,\n });\n }\n } catch (err: unknown) {\n errors.push({\n rowNumber,\n code: \"VALIDATION_RULE_FAILED\",\n reason: err instanceof Error ? err.message : String(err),\n });\n }\n continue;\n }\n }\n\n // Create new record\n try {\n const created = await collService.create(\n {\n title: mapped.title,\n slug: mapped.slug,\n status: mapped.status as any,\n data: mapped.data,\n },\n options.authorId,\n );\n\n createdIds.push(created.id);\n importedCount++;\n\n await this.engine.hooks.doAction(\"cms.transfer_row_imported\", {\n collectionSlug,\n action: \"create\",\n item: created,\n });\n } catch (err: unknown) {\n errors.push({\n rowNumber,\n code: \"VALIDATION_RULE_FAILED\",\n reason: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n const result: TransferImportResult = {\n success: errors.length === 0,\n collectionSlug,\n totalRows: rawRecords.length,\n importedCount,\n updatedCount,\n skippedCount,\n failedCount: rawRecords.length - (importedCount + updatedCount + skippedCount),\n createdIds,\n updatedIds,\n errors,\n };\n\n await this.engine.hooks.doAction(\"cms.transfer_import_completed\", result);\n await this.engine.hooks.doAction(`cms.${collectionSlug}_transferred`, result);\n\n return result;\n }\n\n /**\n * Export CMS collection records to JSON, Excel (.xlsx), or CSV.\n */\n async exportData(\n collectionSlug: string,\n options: TransferExportOptions = {},\n ): Promise<TransferExportResult> {\n const config = this.getCollectionConfigOrThrow(collectionSlug);\n const collService = this.engine.collection(collectionSlug);\n\n // Fetch items with query options\n const query = options.query || { limit: 10000 };\n const paginated = await collService.find(query);\n const items = paginated.items;\n\n // Map records for export\n const exportRecords: Record<string, unknown>[] = [];\n for (const item of items) {\n let mappedRow = mapCmsItemForExport(item, options.mapping, {\n includeId: options.includeId,\n includeTimestamps: options.includeTimestamps,\n });\n\n // Filter hook allowing plugins to inject computed columns\n mappedRow = await this.engine.hooks.applyFilters(\n \"cms.transfer_before_export_row\",\n mappedRow,\n { collectionSlug, item },\n );\n\n exportRecords.push(mappedRow);\n }\n\n const format: SourceFormat = options.format || \"json\";\n const fileName =\n options.fileName ||\n `${collectionSlug}_export_${new Date().toISOString().split(\"T\")[0]}`;\n\n return serializeSource(exportRecords, {\n format,\n fileName,\n sheetName: options.sheetName || config.label,\n });\n }\n\n private getCollectionConfigOrThrow(collectionSlug: string): CollectionConfig {\n const config = this.engine.getCollectionConfig(collectionSlug);\n if (!config) {\n throw new Error(\n `[TransferService] Collection '${collectionSlug}' is not registered in the CMS engine.`,\n );\n }\n return config;\n }\n\n private detectUniqueField(config: CollectionConfig): string | undefined {\n const unique = config.fields.find((f) => Boolean((f as any).unique));\n if (unique) return unique.name;\n const slugField = config.fields.find((f) => f.type === \"slug\" || f.name === \"slug\");\n if (slugField) return slugField.name;\n return undefined;\n }\n}\n","/**\n * @azlib/cms - Universal Transfer Web Standard HTTP API Routes\n */\n\nimport type { CMSPluginContext } from \"../../core/plugin.js\";\nimport type { TransferService } from \"./service.js\";\nimport type {\n DataMappingDefinition,\n SourceFormat,\n TransferPluginOptions,\n} from \"./types.js\";\n\nfunction json(data: unknown, status = 200, headers: HeadersInit = {}): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Access-Control-Allow-Origin\": \"*\",\n ...headers,\n },\n });\n}\n\nfunction badRequest(message: string): Response {\n return json({ error: message }, 400);\n}\n\nfunction notFound(message: string): Response {\n return json({ error: message }, 404);\n}\n\nexport function registerTransferRoutes(\n ctx: CMSPluginContext,\n service: TransferService,\n options: TransferPluginOptions = {},\n): void {\n const prefix = (options.apiPrefix ?? \"/api/transfer\").replace(/\\/+$/, \"\");\n\n // 1. GET /api/transfer/collections - Dynamic listing of all collections across all plugins\n ctx.registerRoute(\"GET\", `${prefix}/collections`, async () => {\n try {\n const collections = service.listCollections();\n return json({ collections });\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // 2. GET /api/transfer/presets - List all registered presets\n ctx.registerRoute(\"GET\", `${prefix}/presets`, async (_req, { url }) => {\n try {\n const collectionSlug = url.searchParams.get(\"collection\") || undefined;\n const presets = service.getPresets(collectionSlug);\n return json({ presets });\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // 3. POST /api/transfer/presets - Register custom preset\n ctx.registerRoute(\"POST\", `${prefix}/presets`, async (req) => {\n try {\n const body = (await req.json()) as DataMappingDefinition;\n if (!body.collectionSlug || !Array.isArray(body.fields)) {\n return badRequest(\"collectionSlug and fields array are required.\");\n }\n service.registerPreset(body);\n return json({ success: true, preset: body }, 201);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // 4. GET /api/transfer/:collection/schema - Dynamic collection schema & template\n ctx.registerRoute(\"GET\", `${prefix}/:collection/schema`, async (_req, { params }) => {\n try {\n const schema = service.getCollectionSchema(params.collection);\n const template = service.getMappingTemplate(params.collection);\n return json({ schema, template });\n } catch (err: unknown) {\n return notFound(err instanceof Error ? err.message : String(err));\n }\n });\n\n // 5. POST /api/transfer/inspect - Inspect uploaded file or payload\n ctx.registerRoute(\"POST\", `${prefix}/inspect`, async (req) => {\n try {\n const payload = await extractPayload(req);\n const result = await service.inspectSource(payload.data, {\n collectionSlug: payload.collectionSlug,\n format: payload.format,\n fileName: payload.fileName,\n sheetName: payload.sheetName,\n });\n return json(result);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // 6. POST /api/transfer/:collection/preview - Dry-run validation\n ctx.registerRoute(\"POST\", `${prefix}/:collection/preview`, async (req, { params }) => {\n try {\n const payload = await extractPayload(req);\n const result = await service.validateImport(\n params.collection,\n payload.data,\n payload.mapping,\n {\n format: payload.format,\n fileName: payload.fileName,\n sheetName: payload.sheetName,\n onDuplicate: payload.onDuplicate,\n },\n );\n return json(result);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // 7. POST /api/transfer/:collection/import - Execute import\n ctx.registerRoute(\"POST\", `${prefix}/:collection/import`, async (req, { params }) => {\n try {\n const payload = await extractPayload(req);\n const result = await service.importData(\n params.collection,\n payload.data,\n payload.mapping,\n {\n format: payload.format,\n fileName: payload.fileName,\n sheetName: payload.sheetName,\n onDuplicate: payload.onDuplicate,\n uniqueIdentifierField: payload.uniqueIdentifierField,\n abortOnError: payload.abortOnError,\n authorId: payload.authorId,\n revisionNote: payload.revisionNote,\n },\n );\n return json(result, result.success ? 200 : 207);\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // 8. POST /api/transfer/:collection/export - Export with JSON body configuration\n ctx.registerRoute(\"POST\", `${prefix}/:collection/export`, async (req, { params }) => {\n try {\n const body = (await req.json()) as {\n format?: SourceFormat;\n mapping?: DataMappingDefinition;\n query?: any;\n fileName?: string;\n sheetName?: string;\n includeId?: boolean;\n includeTimestamps?: boolean;\n };\n\n const result = await service.exportData(params.collection, {\n format: body.format,\n mapping: body.mapping,\n query: body.query,\n fileName: body.fileName,\n sheetName: body.sheetName,\n includeId: body.includeId,\n includeTimestamps: body.includeTimestamps,\n });\n\n return new Response(result.data as any, {\n status: 200,\n headers: {\n \"Content-Type\": result.mimeType,\n \"Content-Disposition\": `attachment; filename=\"${result.fileName}\"`,\n \"Access-Control-Allow-Origin\": \"*\",\n },\n });\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n\n // 9. GET /api/transfer/:collection/export - Export with URL query parameters\n ctx.registerRoute(\"GET\", `${prefix}/:collection/export`, async (_req, { params, url }) => {\n try {\n const format = (url.searchParams.get(\"format\") as SourceFormat) || \"json\";\n const fileName = url.searchParams.get(\"fileName\") || undefined;\n const status = url.searchParams.get(\"status\") || undefined;\n const search = url.searchParams.get(\"search\") || undefined;\n\n const result = await service.exportData(params.collection, {\n format,\n fileName,\n query: {\n status: status as any,\n search,\n },\n });\n\n return new Response(result.data as any, {\n status: 200,\n headers: {\n \"Content-Type\": result.mimeType,\n \"Content-Disposition\": `attachment; filename=\"${result.fileName}\"`,\n \"Access-Control-Allow-Origin\": \"*\",\n },\n });\n } catch (err: unknown) {\n return badRequest(err instanceof Error ? err.message : String(err));\n }\n });\n}\n\n/**\n * Helper to extract payload and options from JSON or Multipart requests.\n */\nasync function extractPayload(req: Request): Promise<{\n data: unknown;\n collectionSlug?: string;\n format?: SourceFormat;\n fileName?: string;\n sheetName?: string;\n mapping?: DataMappingDefinition;\n onDuplicate?: \"error\" | \"update\" | \"skip\";\n uniqueIdentifierField?: string;\n abortOnError?: boolean;\n authorId?: string;\n revisionNote?: string;\n}> {\n const contentType = req.headers.get(\"content-type\") || \"\";\n\n if (contentType.includes(\"multipart/form-data\")) {\n const formData = await req.formData();\n const file = formData.get(\"file\");\n let data: unknown = null;\n let fileName: string | undefined;\n\n if (file && typeof file === \"object\" && \"arrayBuffer\" in file) {\n const blob = file as Blob;\n data = new Uint8Array(await blob.arrayBuffer());\n fileName = (file as any).name;\n }\n\n const mappingRaw = formData.get(\"mapping\");\n const mapping = mappingRaw ? JSON.parse(String(mappingRaw)) : undefined;\n\n return {\n data,\n collectionSlug: (formData.get(\"collectionSlug\") as string) || undefined,\n format: (formData.get(\"format\") as SourceFormat) || undefined,\n fileName: (formData.get(\"fileName\") as string) || fileName,\n sheetName: (formData.get(\"sheetName\") as string) || undefined,\n mapping,\n onDuplicate: (formData.get(\"onDuplicate\") as any) || undefined,\n uniqueIdentifierField: (formData.get(\"uniqueIdentifierField\") as string) || undefined,\n abortOnError: formData.get(\"abortOnError\") === \"true\",\n authorId: (formData.get(\"authorId\") as string) || undefined,\n revisionNote: (formData.get(\"revisionNote\") as string) || undefined,\n };\n }\n\n // Standard JSON payload\n const body = (await req.json()) as any;\n let data = body.data;\n\n // Handle base64 encoded binary file if supplied\n if (typeof body.base64 === \"string\") {\n data = Buffer.from(body.base64, \"base64\");\n }\n\n return {\n data: data !== undefined ? data : body,\n collectionSlug: body.collectionSlug,\n format: body.format,\n fileName: body.fileName,\n sheetName: body.sheetName,\n mapping: body.mapping,\n onDuplicate: body.onDuplicate,\n uniqueIdentifierField: body.uniqueIdentifierField,\n abortOnError: body.abortOnError,\n authorId: body.authorId,\n revisionNote: body.revisionNote,\n };\n}\n","/**\n * @azlib/cms - Universal Transfer Headless Client SDK Extension\n */\n\nimport type { CMSClient } from \"../../client/cms-client.js\";\nimport { TransferService } from \"./service.js\";\nimport type {\n CollectionSchemaSummary,\n DataMappingDefinition,\n SourceFormat,\n SourceInspectionResult,\n TransferExportOptions,\n TransferExportResult,\n TransferImportOptions,\n TransferImportResult,\n TransferPluginOptions,\n ValidationResult,\n} from \"./types.js\";\n\nexport class TransferClient {\n private service?: TransferService;\n private prefix: string;\n\n constructor(\n private client: CMSClient,\n private options: TransferPluginOptions = {},\n ) {\n this.prefix = (options.apiPrefix ?? \"/api/transfer\").replace(/\\/+$/, \"\");\n const engine = client.getEngine();\n if (engine) {\n this.service = new TransferService(engine, options);\n }\n }\n\n /**\n * List all registered collections across all active plugins.\n */\n async listCollections(): Promise<CollectionSchemaSummary[]> {\n if (this.service) {\n return this.service.listCollections();\n }\n const res = await this.client.request<{ collections: CollectionSchemaSummary[] }>(\n `${this.prefix}/collections`,\n );\n return res.collections;\n }\n\n /**\n * Get the collection schema and default mapping template.\n */\n async getSchema(collectionSlug: string): Promise<{\n schema: CollectionSchemaSummary;\n template: DataMappingDefinition;\n }> {\n if (this.service) {\n return {\n schema: this.service.getCollectionSchema(collectionSlug),\n template: this.service.getMappingTemplate(collectionSlug),\n };\n }\n return this.client.request<{\n schema: CollectionSchemaSummary;\n template: DataMappingDefinition;\n }>(`${this.prefix}/${collectionSlug}/schema`);\n }\n\n /**\n * Inspect a source file or payload.\n */\n async inspect(\n data: unknown,\n options: {\n collectionSlug?: string;\n format?: SourceFormat;\n fileName?: string;\n sheetName?: string;\n } = {},\n ): Promise<SourceInspectionResult> {\n if (this.service) {\n return this.service.inspectSource(data, options);\n }\n return this.client.request<SourceInspectionResult>(`${this.prefix}/inspect`, {\n method: \"POST\",\n body: JSON.stringify({ data, ...options }),\n });\n }\n\n /**\n * Dry-run validation of a source batch against a target collection and database constraints.\n */\n async preview(\n collectionSlug: string,\n data: unknown,\n mapping?: DataMappingDefinition,\n options: {\n format?: SourceFormat;\n fileName?: string;\n sheetName?: string;\n onDuplicate?: \"error\" | \"update\" | \"skip\";\n } = {},\n ): Promise<ValidationResult> {\n if (this.service) {\n return this.service.validateImport(collectionSlug, data, mapping, options);\n }\n return this.client.request<ValidationResult>(\n `${this.prefix}/${collectionSlug}/preview`,\n {\n method: \"POST\",\n body: JSON.stringify({ data, mapping, ...options }),\n },\n );\n }\n\n /**\n * Execute an import batch into a target collection.\n */\n async import(\n collectionSlug: string,\n data: unknown,\n mapping?: DataMappingDefinition,\n options: TransferImportOptions & {\n format?: SourceFormat;\n fileName?: string;\n sheetName?: string;\n } = {},\n ): Promise<TransferImportResult> {\n if (this.service) {\n return this.service.importData(collectionSlug, data, mapping, options);\n }\n return this.client.request<TransferImportResult>(\n `${this.prefix}/${collectionSlug}/import`,\n {\n method: \"POST\",\n body: JSON.stringify({ data, mapping, ...options }),\n },\n );\n }\n\n /**\n * Export collection records to JSON, Excel, or CSV.\n */\n async export(\n collectionSlug: string,\n options: TransferExportOptions = {},\n ): Promise<TransferExportResult> {\n if (this.service) {\n return this.service.exportData(collectionSlug, options);\n }\n const res = await this.client.request<any>(\n `${this.prefix}/${collectionSlug}/export`,\n {\n method: \"POST\",\n body: JSON.stringify(options),\n },\n );\n return res;\n }\n}\n\n/**\n * Access or instantiate the TransferClient associated with a CMSClient instance.\n */\nexport function getTransferClient(\n client: CMSClient,\n options?: TransferPluginOptions,\n): TransferClient {\n if ((client as any).__transferClient) {\n return (client as any).__transferClient;\n }\n const tc = new TransferClient(client, options);\n (client as any).__transferClient = tc;\n return tc;\n}\n","/**\n * @azlib/cms - Built-in Universal Transfer Plugin\n */\n\nimport { definePlugin, type CMSPlugin } from \"../../core/plugin.js\";\nimport type { CMSEngine } from \"../../core/engine.js\";\nimport { TransferService } from \"./service.js\";\nimport { registerTransferRoutes } from \"./routes.js\";\nimport type { TransferPluginOptions } from \"./types.js\";\n\nexport * from \"./types.js\";\nexport * from \"./service.js\";\nexport * from \"./client.js\";\nexport * from \"./mapping.js\";\nexport * from \"./inspect.js\";\nexport * from \"./validator.js\";\nexport * from \"./parsers/index.js\";\nexport * from \"./serializers/index.js\";\nexport * from \"./presets/hrms.js\";\n\n/**\n * Built-in Universal Data Transfer plugin factory for @azlib/cms.\n * Equips the CMS engine with dynamic, schema-driven import and export capabilities\n * across all collections, featuring file schema discovery, definition mapping,\n * multi-level data validation, database constraint verification, and multi-format support.\n */\nexport const transferPlugin = definePlugin<TransferPluginOptions | void>(\n (options: TransferPluginOptions | void): CMSPlugin => {\n const opts: TransferPluginOptions = options || {};\n\n return {\n name: \"transfer\",\n version: \"1.0.0\",\n description:\n \"Universal schema-driven data transfer plugin supporting import/export, definition mapping, and constraint validation\",\n\n setup(ctx) {\n const service = new TransferService(ctx.engine, opts);\n (ctx.engine as any).__transferService = service;\n\n if (opts.enableRoutes !== false) {\n registerTransferRoutes(ctx, service, opts);\n }\n },\n };\n },\n);\n\n/**\n * Retrieve the active TransferService instance associated with a CMSEngine.\n */\nexport function getTransferService(\n engine: CMSEngine,\n options?: TransferPluginOptions,\n): TransferService {\n if ((engine as any).__transferService) {\n return (engine as any).__transferService;\n }\n const service = new TransferService(engine, options);\n (engine as any).__transferService = service;\n return service;\n}\n"],"mappings":"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"}
|