@adminforge/core 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/.turbo/turbo-build.log +56 -0
  2. package/CHANGELOG.md +32 -0
  3. package/LICENSE +21 -0
  4. package/bin/adminforge.js +317 -0
  5. package/dist/auth-client.cjs +45 -0
  6. package/dist/auth-client.cjs.map +1 -0
  7. package/dist/auth-client.d.cts +17 -0
  8. package/dist/auth-client.d.ts +17 -0
  9. package/dist/auth-client.js +20 -0
  10. package/dist/auth-client.js.map +1 -0
  11. package/dist/auth.cjs +65 -0
  12. package/dist/auth.cjs.map +1 -0
  13. package/dist/auth.d.cts +21 -0
  14. package/dist/auth.d.ts +21 -0
  15. package/dist/auth.js +36 -0
  16. package/dist/auth.js.map +1 -0
  17. package/dist/client-D0cjJVsn.d.ts +20 -0
  18. package/dist/client-sRnmZ-Y9.d.cts +20 -0
  19. package/dist/index-CyzxaE7n.d.cts +124 -0
  20. package/dist/index-CyzxaE7n.d.ts +124 -0
  21. package/dist/index.cjs +453 -0
  22. package/dist/index.cjs.map +1 -0
  23. package/dist/index.d.cts +65 -0
  24. package/dist/index.d.ts +65 -0
  25. package/dist/index.js +410 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/next.cjs +839 -0
  28. package/dist/next.cjs.map +1 -0
  29. package/dist/next.d.cts +84 -0
  30. package/dist/next.d.ts +84 -0
  31. package/dist/next.js +800 -0
  32. package/dist/next.js.map +1 -0
  33. package/dist/styles.css +763 -0
  34. package/dist/styles.css.map +1 -0
  35. package/dist/styles.d.cts +2 -0
  36. package/dist/styles.d.ts +2 -0
  37. package/dist/ui.cjs +2500 -0
  38. package/dist/ui.cjs.map +1 -0
  39. package/dist/ui.d.cts +119 -0
  40. package/dist/ui.d.ts +119 -0
  41. package/dist/ui.js +2448 -0
  42. package/dist/ui.js.map +1 -0
  43. package/eslint.config.js +35 -0
  44. package/package.json +99 -0
  45. package/src/api/controller.ts +234 -0
  46. package/src/api/index.ts +4 -0
  47. package/src/api/next.ts +281 -0
  48. package/src/api/security/agent-auth.ts +134 -0
  49. package/src/auth/config.ts +20 -0
  50. package/src/auth/index.ts +3 -0
  51. package/src/auth/middleware.ts +15 -0
  52. package/src/auth/provider.tsx +28 -0
  53. package/src/core/fields/index.ts +119 -0
  54. package/src/core/hooks/index.ts +60 -0
  55. package/src/core/index.ts +43 -0
  56. package/src/core/registry/index.ts +22 -0
  57. package/src/core/schema/collection.ts +12 -0
  58. package/src/core/schema/config.ts +11 -0
  59. package/src/core/schema/normalize.ts +32 -0
  60. package/src/core/types/index.ts +114 -0
  61. package/src/db/client.ts +146 -0
  62. package/src/db/index.ts +3 -0
  63. package/src/db/schema-generator.ts +104 -0
  64. package/src/fields/index.ts +1 -0
  65. package/src/index.ts +4 -0
  66. package/src/next.ts +3 -0
  67. package/src/styles/adminforge.css +840 -0
  68. package/src/ui/AdminDashboard.tsx +176 -0
  69. package/src/ui/AdminForgeContext.tsx +64 -0
  70. package/src/ui/components/AdminLayout.tsx +107 -0
  71. package/src/ui/form-engine/FormEngine.tsx +250 -0
  72. package/src/ui/form-engine/ImageUpload.tsx +68 -0
  73. package/src/ui/form-engine/RelationInput.tsx +215 -0
  74. package/src/ui/form-engine/RichTextEditor.tsx +708 -0
  75. package/src/ui/index.ts +18 -0
  76. package/src/ui/screens/AdminPage.tsx +162 -0
  77. package/src/ui/screens/AgentTokenPage.tsx +232 -0
  78. package/src/ui/screens/CollectionFormPage.tsx +135 -0
  79. package/src/ui/screens/CollectionListPage.tsx +170 -0
  80. package/src/ui/screens/CollectionSchemaPage.tsx +180 -0
  81. package/src/ui/screens/RoleDetailPage.tsx +147 -0
  82. package/src/ui/screens/RolesListPage.tsx +57 -0
  83. package/src/ui/table-engine/TableEngine.tsx +157 -0
  84. package/src/ui.ts +3 -0
  85. package/tsconfig.json +10 -0
  86. package/tsup.config.ts +54 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/security/agent-auth.ts","../src/core/schema/config.ts","../src/core/schema/collection.ts","../src/core/schema/normalize.ts","../src/core/fields/index.ts","../src/core/registry/index.ts","../src/core/hooks/index.ts","../src/core/index.ts","../src/next.ts","../src/api/controller.ts","../src/api/index.ts","../src/api/next.ts","../src/auth/config.ts","../src/auth/middleware.ts"],"sourcesContent":["import jwt from \"jsonwebtoken\";\nimport crypto from \"crypto\";\n\n/**\n * --- Security Model Definitions ---\n */\n\nexport type Action = \"create\" | \"read\" | \"update\" | \"delete\";\n\nexport type AgentTokenPayload = {\n sub: string; // userId\n role: string;\n scope: string[]; // format: \"collection:action\"\n iat: number;\n exp: number;\n iss: \"adminforge\";\n aud: \"agent\";\n sessionId: string;\n};\n\nexport type AgentSession = AgentTokenPayload;\n\nexport type SecurityContext = {\n user?: any; // Replace with User type from your auth package\n agent?: AgentSession;\n source: \"user\" | \"agent\";\n};\n\nfunction getSecret(): string {\n const secret = process.env.ADMINFORGE_SECRET;\n if (!secret) {\n throw new Error(\"ADMINFORGE_SECRET env var is required. Generate one with: openssl rand -hex 32\");\n }\n return secret;\n}\n\n/**\n * --- Utilities ---\n */\n\nfunction normalizeScope(scope: string): string {\n const normalized = scope.trim().toLowerCase();\n if (!/^[a-z0-9_-]+:[a-z]+$/.test(normalized)) {\n throw new Error(`Malformed scope format: ${scope}`);\n }\n return normalized;\n}\n\nfunction assertValidAction(action: string): Action {\n const validActions: Action[] = [\"create\", \"read\", \"update\", \"delete\"];\n if (!validActions.includes(action as Action)) {\n throw new Error(`Invalid action: ${action}`);\n }\n return action as Action;\n}\n\nfunction assertValidCollection(collection: string): string {\n if (!/^[a-z0-9_-]+$/.test(collection)) {\n throw new Error(`Invalid collection name: ${collection}`);\n }\n return collection;\n}\n\n/**\n * --- Token Lifecycle ---\n */\n\nexport function generateAgentToken(\n userId: string,\n role: string,\n scopes: string[],\n expiresInSeconds: number = 600\n): string {\n const normalizedScopes = scopes.map(normalizeScope);\n\n return jwt.sign(\n {\n sub: userId,\n role,\n scope: normalizedScopes,\n sessionId: crypto.randomUUID(),\n },\n getSecret(),\n {\n expiresIn: expiresInSeconds,\n issuer: \"adminforge\",\n audience: \"agent\",\n }\n );\n}\n\n/**\n * --- Verification & Enforcement ---\n */\n\n// Stub for revocation capability\nfunction isRevoked(sessionId: string): boolean {\n // In V1, we return false. V2 will check against a Redis/DB blacklist.\n return false;\n}\n\nexport function verifyAgentToken(token: string): AgentTokenPayload {\n try {\n const payload = jwt.verify(token, getSecret(), {\n issuer: \"adminforge\",\n audience: \"agent\",\n }) as unknown as AgentTokenPayload;\n\n if (!payload.sub) throw new Error(\"Missing userId (sub)\");\n if (!payload.role) throw new Error(\"Missing role\");\n if (!Array.isArray(payload.scope)) throw new Error(\"Invalid scope format\");\n\n if (isRevoked(payload.sessionId)) {\n throw new Error(\"Session revoked\");\n }\n\n // Semantic normalization\n payload.scope = payload.scope.map(normalizeScope);\n\n return payload;\n } catch (error: any) {\n throw new Error(`Unauthorized: ${error.message}`);\n }\n}\n\nexport function assertScope(agent: AgentSession, collection: string, action: Action): void {\n const validColl = assertValidCollection(collection);\n const validAction = assertValidAction(action);\n const key = `${validColl}:${validAction}`.toLowerCase();\n\n if (!agent.scope.includes(key)) {\n throw new Error(`Forbidden: Missing scope ${key}`);\n }\n}\n","import type { AdminForgeConfig, CollectionDefinition, AuthConfig } from \"../types/index.js\";\n\nexport function defineConfig(config: {\n collections: CollectionDefinition[];\n auth?: AuthConfig;\n}): AdminForgeConfig {\n return {\n collections: config.collections,\n auth: config.auth ?? { enabled: false },\n };\n}\n","import type { CollectionDefinition, CollectionInput } from \"../types/index.js\";\n\nexport function collection(input: CollectionInput): CollectionDefinition {\n return {\n name: input.name,\n label: input.label ?? input.name.charAt(0).toUpperCase() + input.name.slice(1),\n icon: input.icon,\n fields: input.fields,\n hooks: input.hooks,\n access: input.access,\n };\n}\n","import type { AdminForgeConfig } from \"../types/index.js\";\n\nexport type NormalizedSchema = AdminForgeConfig;\n\nexport function normalize(config: AdminForgeConfig): NormalizedSchema {\n return {\n collections: config.collections.map((c) => ({\n ...c,\n label: c.label ?? c.name.charAt(0).toUpperCase() + c.name.slice(1),\n })),\n auth: config.auth ?? { enabled: false },\n };\n}\n\n/**\n * Removes non-serializable parts of the config (like Zod schemas)\n * so it can be passed from Server Components to Client Components.\n */\nexport function serializeConfig(config: AdminForgeConfig): any {\n return {\n ...config,\n collections: config.collections.map((c) => ({\n ...c,\n fields: Object.fromEntries(\n Object.entries(c.fields).map(([name, field]) => {\n const { validation, ...rest } = field;\n return [name, rest];\n })\n ),\n })),\n };\n}\n","import { z } from \"zod\";\nimport type {\n FieldDefinition,\n FieldMeta,\n FieldOptions,\n TextOptions,\n BooleanOptions,\n RichTextOptions,\n SlugOptions,\n RelationOptions,\n DateOptions,\n ImageOptions,\n} from \"../types/index.js\";\n\nfunction fieldMeta(options: FieldOptions = {}): FieldMeta {\n return {\n required: Boolean(options.required),\n unique: Boolean(options.unique),\n default: options.default,\n label: options.label,\n hidden: options.hidden,\n readOnly: options.readOnly,\n description: options.description,\n };\n}\n\nfunction text(options: TextOptions = {}): FieldDefinition {\n return {\n type: \"text\",\n db: { type: \"String\", nullable: !options.required, unique: options.unique, default: options.default },\n access: options.access,\n ui: { component: \"text\", props: { label: options.label, hidden: options.hidden, readOnly: options.readOnly } },\n validation: options.required ? z.string().min(1) : z.string().optional(),\n meta: fieldMeta(options),\n };\n}\n\nfunction boolean(options: BooleanOptions = {}): FieldDefinition {\n return {\n type: \"boolean\",\n db: { type: \"Boolean\", nullable: !options.required, default: options.default ?? false },\n access: options.access,\n ui: { component: \"boolean\", props: { label: options.label, hidden: options.hidden, readOnly: options.readOnly } },\n validation: options.required ? z.boolean() : z.boolean().optional(),\n meta: fieldMeta(options),\n };\n}\n\nfunction richText(options: RichTextOptions = {}): FieldDefinition {\n return {\n type: \"richText\",\n db: { type: \"String\", nullable: !options.required },\n access: options.access,\n ui: { component: \"richText\", props: { label: options.label, hidden: options.hidden, readOnly: options.readOnly } },\n validation: options.required ? z.string().min(1) : z.string().optional(),\n meta: fieldMeta(options),\n };\n}\n\nfunction slug(options: SlugOptions): FieldDefinition {\n return {\n type: \"slug\",\n db: { type: \"String\", nullable: !options.required, unique: options.unique ?? true },\n access: options.access,\n ui: { component: \"slug\", props: { from: options.from, label: options.label, hidden: options.hidden, readOnly: options.readOnly } },\n validation: options.required\n ? z.string().regex(/^[a-z0-9-]+$/)\n : z.string().regex(/^[a-z0-9-]+$/).optional(),\n hooks: { beforeSave: (value: unknown) => {\n if (typeof value === \"string\") return value.toLowerCase().replace(/\\s+/g, \"-\").replace(/[^a-z0-9-]/g, \"\");\n return value;\n }},\n meta: { ...fieldMeta(options), unique: options.unique ?? true },\n };\n}\n\nfunction relation(options: RelationOptions): FieldDefinition {\n const isMulti = options.type === \"many-to-many\" || options.type === \"one-to-many\";\n return {\n type: \"relation\",\n db: { type: \"String\", nullable: !options.required, references: { model: options.to, field: \"id\" }, relationType: options.type },\n access: options.access,\n ui: { component: \"relation\", props: { to: options.to, relationType: options.type, label: options.label, hidden: options.hidden, readOnly: options.readOnly } },\n validation: isMulti\n ? (options.required ? z.array(z.string()).min(1) : z.array(z.string()).optional())\n : (options.required ? z.string().min(1) : z.string().optional()),\n meta: fieldMeta(options),\n };\n}\n\nfunction date(options: DateOptions = {}): FieldDefinition {\n return {\n type: \"date\",\n db: { type: \"DateTime\", nullable: !options.required },\n access: options.access,\n ui: { component: \"date\", props: { label: options.label, hidden: options.hidden, readOnly: options.readOnly } },\n validation: options.required ? z.string().datetime() : z.string().datetime().optional(),\n hooks: { beforeSave: (value: unknown) => {\n if (options.autoCreate && !value) return new Date().toISOString();\n return value;\n }},\n meta: fieldMeta(options),\n };\n}\n\nfunction image(options: ImageOptions = {}): FieldDefinition {\n return {\n type: \"image\",\n db: { type: \"String\", nullable: true },\n access: options.access,\n ui: { component: \"image\", props: { label: options.label, hidden: options.hidden, readOnly: options.readOnly } },\n validation: z.string().optional(),\n meta: fieldMeta(options),\n };\n}\n\nexport const fields = {\n text, boolean, richText, slug, relation, date, image,\n} as const;\n","import type { FieldDefinition } from \"../types/index.js\";\n\nconst fieldRegistry = new Map<string, FieldDefinition>();\n\nexport function registerField(name: string, definition: FieldDefinition): void {\n if (fieldRegistry.has(name)) {\n throw new Error(`Field \"${name}\" is already registered`);\n }\n fieldRegistry.set(name, definition);\n}\n\nexport function getField(name: string): FieldDefinition | undefined {\n return fieldRegistry.get(name);\n}\n\nexport function getRegisteredFields(): Map<string, FieldDefinition> {\n return new Map(fieldRegistry);\n}\n\nexport function clearRegistry(): void {\n fieldRegistry.clear();\n}\n","import type { CollectionHooks } from \"../types/index.js\";\n\nexport async function executeBeforeCreate(\n hooks: CollectionHooks | undefined,\n data: Record<string, unknown>\n): Promise<Record<string, unknown>> {\n if (hooks?.beforeCreate) {\n return await hooks.beforeCreate({ data });\n }\n return data;\n}\n\nexport async function executeAfterCreate(\n hooks: CollectionHooks | undefined,\n data: Record<string, unknown>,\n id: string\n): Promise<void> {\n if (hooks?.afterCreate) {\n await hooks.afterCreate({ data, id });\n }\n}\n\nexport async function executeBeforeUpdate(\n hooks: CollectionHooks | undefined,\n data: Record<string, unknown>,\n id: string\n): Promise<Record<string, unknown>> {\n if (hooks?.beforeUpdate) {\n return await hooks.beforeUpdate({ data, id });\n }\n return data;\n}\n\nexport async function executeAfterUpdate(\n hooks: CollectionHooks | undefined,\n data: Record<string, unknown>,\n id: string\n): Promise<void> {\n if (hooks?.afterUpdate) {\n await hooks.afterUpdate({ data, id });\n }\n}\n\nexport async function executeBeforeDelete(\n hooks: CollectionHooks | undefined,\n id: string\n): Promise<void> {\n if (hooks?.beforeDelete) {\n await hooks.beforeDelete({ id });\n }\n}\n\nexport async function executeAfterDelete(\n hooks: CollectionHooks | undefined,\n id: string\n): Promise<void> {\n if (hooks?.afterDelete) {\n await hooks.afterDelete({ id });\n }\n}\n","export { defineConfig } from \"./schema/config.js\";\nexport { collection } from \"./schema/collection.js\";\nexport { normalize, serializeConfig } from \"./schema/normalize.js\";\nexport type { NormalizedSchema } from \"./schema/normalize.js\";\nexport { fields } from \"./fields/index.js\";\nexport { registerField, getField, getRegisteredFields, clearRegistry } from \"./registry/index.js\";\nexport {\n executeBeforeCreate,\n executeAfterCreate,\n executeBeforeUpdate,\n executeAfterUpdate,\n executeBeforeDelete,\n executeAfterDelete,\n} from \"./hooks/index.js\";\nexport type {\n FieldDefinition,\n FieldDBMapping,\n FieldUI,\n FieldHooks,\n FieldMeta,\n CollectionDefinition,\n CollectionHooks,\n AdminForgeConfig,\n AuthConfig,\n AccessConfig,\n RelationType,\n TextOptions,\n BooleanOptions,\n RichTextOptions,\n SlugOptions,\n RelationOptions,\n DateOptions,\n ImageOptions,\n} from \"./types/index.js\";\n\n/**\n * Utility type to infer the record structure from a CollectionDefinition.\n */\nexport type InferRecord<T extends { fields: Record<string, any> }> = {\n id: string;\n} & {\n [K in keyof T[\"fields\"]]: any; // We'll refine this in the future with proper field-to-type mapping\n};\n","export * from \"./api/index.js\";\nexport * from \"./api/next.js\";\nexport * from \"./auth/index.js\";\n","import type { AdminForgeConfig, CollectionDefinition, AccessConfig } from \"../core\";\nimport type { DbClient } from \"../db\";\nimport { z } from \"zod\";\nimport { assertScope, type SecurityContext, type Action } from \"./security/agent-auth\";\n\nfunction buildValidationSchema(collection: CollectionDefinition): z.ZodObject<Record<string, z.ZodTypeAny>> {\n const shape: Record<string, z.ZodTypeAny> = {};\n for (const [name, field] of Object.entries(collection.fields)) {\n shape[name] = field.validation;\n }\n return z.object(shape);\n}\n\ninterface AdminSession {\n user: { id: string; email: string; role?: string } | null;\n role?: string; // Support for root-level role\n}\n\nfunction hasAccess(access: AccessConfig | undefined, operation: string, role?: string): boolean {\n if (!access) return true;\n const allowed = access[operation as keyof AccessConfig];\n if (!allowed || !Array.isArray(allowed)) return true;\n if (!role) return false;\n return allowed.includes(role);\n}\n\nexport type AccessInfo = SecurityContext;\n\nexport interface Controller {\n list: (args?: { where?: Record<string, unknown>; orderBy?: Record<string, string>; page?: number; pageSize?: number; search?: string }) => Promise<{ data: unknown[]; total: number; page: number; pageSize: number }>;\n get: (id: string) => Promise<unknown | null>;\n create: (data: Record<string, unknown>) => Promise<unknown>;\n update: (id: string, data: Record<string, unknown>) => Promise<unknown>;\n delete: (id: string) => Promise<unknown>;\n}\n\nexport function createController(\n collection: CollectionDefinition,\n db: DbClient,\n session?: SecurityContext,\n): Controller {\n const validationSchema = buildValidationSchema(collection);\n const role = session?.user?.role || session?.agent?.role;\n const actorId = session?.user?.id || session?.agent?.sub;\n\n function requireAccess(operation: Action) {\n console.error(`[ACL] Operation: ${operation}, Collection: ${collection.name}, Role: ${role}, Source: ${session?.source}`);\n \n // 1. Scope Enforcement (limiter)\n if (session?.agent) {\n assertScope(session.agent, collection.name, operation);\n }\n\n // 2. RBAC Enforcement (authority)\n if (!hasAccess(collection.access, operation, role)) {\n console.warn(`[ACL] DENIED: ${role} not allowed to ${operation} on ${collection.name}. Allowed:`, collection.access?.[operation]);\n throw new Error(`Access denied: ${operation} on ${collection.name}`);\n }\n\n // 3. Audit Logging\n console.error(JSON.stringify({\n timestamp: new Date().toISOString(),\n type: \"mutation_attempt\",\n source: session?.source || \"unknown\",\n userId: actorId || \"anonymous\",\n role: role || \"none\",\n collection: collection.name,\n action: operation,\n sessionId: session?.agent?.sessionId,\n }));\n }\n\n function buildSearchWhere(search?: string): Record<string, unknown> | undefined {\n if (!search) return undefined;\n \n // Find all text-based fields to search in\n const searchFields = Object.entries(collection.fields)\n .filter(([_, field]) => field.type === \"text\" || field.type === \"slug\" || field.type === \"richText\")\n .map(([name]) => name);\n\n if (searchFields.length === 0) return undefined;\n\n return {\n OR: searchFields.map(field => ({\n [field]: { contains: search, mode: 'insensitive' }\n }))\n };\n }\n\n function filterFields(fields: Record<string, unknown>): Record<string, unknown> {\n const filtered: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(fields)) {\n const field = collection.fields[key];\n if (hasAccess(field?.access, \"read\", role)) {\n filtered[key] = value;\n }\n }\n return filtered;\n }\n\n function filterWritableFields(\n fields: Record<string, unknown>,\n operation: \"create\" | \"update\"\n ): Record<string, unknown> {\n const filtered: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(fields)) {\n const field = collection.fields[key];\n if (field && hasAccess(field.access, operation, role)) {\n filtered[key] = value;\n }\n }\n return filtered;\n }\n\n function applyFieldHooks(\n fields: Record<string, unknown>,\n hookName: \"beforeValidate\" | \"beforeSave\"\n ): Record<string, unknown> {\n const next = { ...fields };\n for (const [key, value] of Object.entries(next)) {\n const hook = collection.fields[key]?.hooks?.[hookName];\n if (hook) {\n next[key] = hook(value);\n }\n }\n return next;\n }\n\n function applyDerivedFields(fields: Record<string, unknown>): Record<string, unknown> {\n const next = { ...fields };\n for (const [name, field] of Object.entries(collection.fields)) {\n if (field.type !== \"slug\") continue;\n const current = next[name];\n if (typeof current === \"string\" && current.trim().length > 0) continue;\n const from = field.ui.props?.from;\n if (typeof from !== \"string\") continue;\n const source = next[from];\n if (typeof source !== \"string\" || source.trim().length === 0) continue;\n const slugified = source\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\") // Remove accents\n .replace(/\\s+/g, \"-\") // Replace spaces with -\n .replace(/[^a-z0-9-]/g, \"\") // Remove non-alphanumeric\n .replace(/-+/g, \"-\") // Remove double dashes\n .replace(/^-+|-+$/g, \"\"); // Trim dashes\n\n next[name] = slugified;\n }\n return next;\n }\n\n return {\n async list(args = {}) {\n requireAccess(\"read\");\n const { where, orderBy, page = 1, pageSize = 50, search } = args;\n \n const searchWhere = buildSearchWhere(search);\n const combinedWhere = searchWhere ? { ...where, ...searchWhere } : where;\n \n const skip = (page - 1) * pageSize;\n \n // Default sorting to newest first. \n // We check for 'createdAt' but default to 'id' desc as a safe fallback for all DBs.\n const effectiveOrderBy = orderBy || (collection.fields.createdAt ? { createdAt: 'desc' } : { id: 'desc' });\n\n const [raw, total] = await Promise.all([\n db.findMany(collection.name, { where: combinedWhere, orderBy: effectiveOrderBy, skip, take: pageSize }),\n db.count(collection.name, { where: combinedWhere })\n ]);\n \n const data = (raw as Record<string, unknown>[]).map(filterFields);\n return { data, total, page, pageSize };\n },\n\n async get(id: string) {\n requireAccess(\"read\");\n const raw = await db.findUnique(collection.name, id);\n if (!raw) return null;\n return filterFields(raw as Record<string, unknown>);\n },\n\n async create(data: Record<string, unknown>) {\n requireAccess(\"create\");\n const allowed = filterWritableFields(data, \"create\");\n const withDerived = applyDerivedFields(allowed);\n const beforeValidate = applyFieldHooks(withDerived, \"beforeValidate\");\n const parsed = validationSchema.parse(beforeValidate);\n const beforeSave = applyFieldHooks(parsed, \"beforeSave\");\n const transformed = transformRelations(beforeSave, false);\n return db.create(collection.name, transformed);\n },\n\n async update(id: string, data: Record<string, unknown>) {\n requireAccess(\"update\");\n const allowed = filterWritableFields(data, \"update\");\n const beforeValidate = applyFieldHooks(allowed, \"beforeValidate\");\n const parsed = validationSchema.partial().parse(beforeValidate);\n const beforeSave = applyFieldHooks(parsed, \"beforeSave\");\n const transformed = transformRelations(beforeSave, true);\n return db.update(collection.name, id, transformed);\n },\n\n async delete(id: string) {\n requireAccess(\"delete\");\n return db.delete(collection.name, id);\n },\n };\n\n function transformRelations(data: Record<string, unknown>, isUpdate: boolean) {\n const transformed = { ...data };\n for (const [key, value] of Object.entries(transformed)) {\n const field = collection.fields[key];\n if (field?.type === \"relation\") {\n const relationType = field.db.relationType ?? \"many-to-one\";\n const isMulti = relationType === \"many-to-many\" || relationType === \"one-to-many\";\n\n if (Array.isArray(value)) {\n const ids = value.filter((id): id is string => typeof id === \"string\" && id.length > 0);\n transformed[key] = isUpdate\n ? { set: ids.map((id) => ({ id })) }\n : { connect: ids.map((id) => ({ id })) };\n } else if (!isMulti && typeof value === \"string\" && value.length > 0) {\n transformed[key] = { connect: { id: value } };\n } else if ((value === null || value === \"\") && isUpdate) {\n transformed[key] = { disconnect: true };\n } else if (value === null || value === \"\") {\n delete transformed[key];\n }\n }\n }\n return transformed;\n }\n}\n","export { createController } from \"./controller.js\";\nexport type { Controller } from \"./controller.js\";\nexport * from \"./security/agent-auth.js\";\n\n","import type { AdminForgeConfig, CollectionDefinition } from \"../core\";\nimport type { DbClient } from \"../db\";\nimport { createController } from \"./controller.js\";\nimport { verifyAgentToken, type SecurityContext } from \"./security/agent-auth.js\";\n\ninterface RouteContext {\n params: Promise<Record<string, string>>;\n}\n\nfunction jsonResponse(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\nfunction getBody(request: Request): Promise<Record<string, unknown>> {\n return request.json().catch(() => ({}));\n}\n\ninterface RouteParams {\n config: AdminForgeConfig;\n db: DbClient;\n auth?: any; // The NextAuth auth() function\n}\n\nexport function createRouteHandlers({ config, db, auth }: RouteParams) {\n // We'll create controllers per request to inject the correct security context\n const getSecurity = async (request: Request): Promise<SecurityContext> => {\n const authHeader = request.headers.get(\"authorization\");\n \n if (authHeader?.startsWith(\"Bearer \")) {\n const token = authHeader.split(\" \")[1];\n try {\n const agent = verifyAgentToken(token);\n return {\n source: \"agent\",\n agent,\n user: { id: agent.sub, role: agent.role } \n };\n } catch (e: any) {\n console.error(`[Auth] Agent Verification Failed: ${e.message}`);\n }\n }\n\n // Try to get session via NextAuth if provided\n if (auth) {\n try {\n const session = await auth();\n if (session?.user) {\n return {\n source: \"user\",\n user: {\n id: session.user.id || session.user.email,\n role: (session as any).role || \"user\"\n }\n };\n }\n } catch (e: any) {\n console.error(`[Auth] Session Retrieval Failed: ${e.message}`);\n }\n }\n\n return { source: \"user\" }; \n };\n\n function generateHandlers(collectionName: string) {\n const collection = config.collections.find((c) => c.name === collectionName);\n if (!collection) {\n throw new Error(`Collection \"${collectionName}\" not found in config`);\n }\n\n return {\n GET: async (request: Request, context: RouteContext) => {\n const security = await getSecurity(request);\n const controller = createController(collection, db, security);\n const params = await context.params;\n if (params.id) {\n const result = await controller.get(params.id);\n if (!result) return jsonResponse({ error: \"Not found\" }, 404);\n return jsonResponse(result);\n }\n const url = new URL(request.url);\n const page = parseInt(url.searchParams.get(\"page\") ?? \"1\");\n const pageSize = parseInt(url.searchParams.get(\"pageSize\") ?? \"10\");\n const search = url.searchParams.get(\"search\") ?? undefined;\n const result = await controller.list({ page, pageSize, search });\n return jsonResponse(result);\n },\n\n POST: async (request: Request) => {\n const security = await getSecurity(request);\n const controller = createController(collection, db, security);\n const body = await getBody(request);\n try {\n const result = await controller.create(body);\n return jsonResponse(result, 201);\n } catch (err) {\n const error = err as any;\n if (error.name === \"ZodError\") {\n const issues = error.issues.map((i: any) => `${i.path.join(\".\")}: ${i.message}`).join(\", \");\n return jsonResponse({ error: `Validation failed: ${issues}` }, 400);\n }\n return jsonResponse({ error: error.message }, 400);\n }\n },\n\n PATCH: async (request: Request, context: RouteContext) => {\n const security = await getSecurity(request);\n const controller = createController(collection, db, security);\n const params = await context.params;\n if (!params.id) return jsonResponse({ error: \"ID required\" }, 400);\n const body = await getBody(request);\n try {\n const result = await controller.update(params.id, body);\n return jsonResponse(result);\n } catch (err) {\n const error = err as any;\n if (error.name === \"ZodError\") {\n const issues = error.issues.map((i: any) => `${i.path.join(\".\")}: ${i.message}`).join(\", \");\n return jsonResponse({ error: `Validation failed: ${issues}` }, 400);\n }\n return jsonResponse({ error: error.message }, 400);\n }\n },\n\n DELETE: async (request: Request, context: RouteContext) => {\n const security = await getSecurity(request);\n const controller = createController(collection, db, security);\n const params = await context.params;\n if (!params.id) return jsonResponse({ error: \"ID required\" }, 400);\n try {\n const result = await controller.delete(params.id);\n return jsonResponse(result);\n } catch (err) {\n const error = err as Error;\n return jsonResponse({ error: error.message }, 400);\n }\n },\n };\n }\n\n return { generateHandlers };\n}\n\nexport function createAdminForgeApi({ config, db, auth }: RouteParams) {\n const { generateHandlers } = createRouteHandlers({ config, db, auth });\n\n const getCollectionAndId = (slug: string[]) => {\n const [collectionName, id] = slug;\n const handlers = generateHandlers(collectionName);\n return { handlers, id };\n };\n\n return {\n async GET(request: Request, { params }: { params: Promise<any> }) {\n try {\n const resolvedParams = await params;\n const slug = resolvedParams.slug || resolvedParams.admin || Object.values(resolvedParams)[0] as string[];\n \n // Return serialized config for the UI\n // Detect _config anywhere in the slug to support various mounting points\n if (slug.includes(\"_config\")) {\n if (config.auth?.enabled && auth) {\n try {\n const session = await auth();\n if (!session?.user) {\n return jsonResponse({ error: \"Unauthorized\" }, 401);\n }\n } catch {\n return jsonResponse({ error: \"Unauthorized\" }, 401);\n }\n }\n const { serializeConfig } = await import(\"../core/index.js\");\n return jsonResponse(serializeConfig(config));\n }\n\n const { handlers, id } = getCollectionAndId(slug);\n return handlers.GET(request, { params: Promise.resolve({ id: id || \"\" }) });\n } catch (err) {\n return jsonResponse({ error: (err as Error).message }, 404);\n }\n },\n\n async POST(request: Request, { params }: { params: Promise<any> }) {\n try {\n const resolvedParams = await params;\n const slug = resolvedParams.slug || resolvedParams.admin || Object.values(resolvedParams)[0] as string[];\n \n // Handle Media Uploads\n if (slug[0] === \"_media\") {\n const formData = await request.formData();\n const file = formData.get(\"file\") as File;\n if (!file) return jsonResponse({ error: \"No file uploaded\" }, 400);\n\n const bytes = await file.arrayBuffer();\n const buffer = Buffer.from(bytes);\n\n const path = await import(\"path\");\n const fs = await import(\"fs/promises\");\n const uploadDir = path.join(process.cwd(), \"public\", \"uploads\");\n \n try {\n await fs.mkdir(uploadDir, { recursive: true });\n } catch {}\n\n const filename = `${Date.now()}-${file.name.replace(/\\s+/g, \"-\")}`;\n const filePath = path.join(uploadDir, filename);\n await fs.writeFile(filePath, buffer);\n\n return jsonResponse({ \n url: `/uploads/${filename}`,\n filename\n }, 201);\n }\n\n // Handle Agent Token Generation\n if (slug[0] === \"_tokens\") {\n const { generateAgentToken } = await import(\"./security/agent-auth.js\");\n const body = await request.json();\n const { scope, expiresIn = 600 } = body;\n\n if (!Array.isArray(scope)) {\n return jsonResponse({ error: \"Scope must be an array\" }, 400);\n }\n\n // Validation: Ensure collections exist\n for (const s of scope) {\n const [collection, action] = s.split(\":\");\n const exists = config.collections.find(c => c.name === collection);\n if (!exists) return jsonResponse({ error: `Invalid collection: ${collection}` }, 400);\n if (![\"create\", \"read\", \"update\", \"delete\"].includes(action)) {\n return jsonResponse({ error: `Invalid action: ${action}` }, 400);\n }\n }\n\n // Auth: Get session\n let userId = \"admin\";\n let role = \"admin\";\n if (auth) {\n const session = await auth();\n if (session?.user) {\n userId = session.user.id || session.user.email;\n role = (session as any).role || \"admin\";\n }\n }\n\n const token = generateAgentToken(userId, role, scope, expiresIn);\n return jsonResponse({ token });\n }\n\n const { handlers } = getCollectionAndId(slug);\n return handlers.POST(request);\n } catch (err) {\n return jsonResponse({ error: (err as Error).message }, 404);\n }\n },\n\n async PATCH(request: Request, { params }: { params: Promise<any> }) {\n try {\n const resolvedParams = await params;\n const slug = resolvedParams.slug || resolvedParams.admin || Object.values(resolvedParams)[0] as string[];\n const { handlers, id } = getCollectionAndId(slug);\n return handlers.PATCH(request, { params: Promise.resolve({ id: id || \"\" }) });\n } catch (err) {\n return jsonResponse({ error: (err as Error).message }, 404);\n }\n },\n\n async DELETE(request: Request, { params }: { params: Promise<any> }) {\n try {\n const resolvedParams = await params;\n const slug = resolvedParams.slug || resolvedParams.admin || Object.values(resolvedParams)[0] as string[];\n const { handlers, id } = getCollectionAndId(slug);\n return handlers.DELETE(request, { params: Promise.resolve({ id: id || \"\" }) });\n } catch (err) {\n return jsonResponse({ error: (err as Error).message }, 404);\n }\n },\n };\n}\n","interface AuthConfigOptions {\n enabled: boolean;\n secret?: string;\n}\n\nexport function createAuthConfig(options: AuthConfigOptions) {\n return {\n ...options,\n providers: [\"credentials\"] as const,\n };\n}\n\nexport const auth = {\n providers: {\n credentials: {\n id: \"credentials\",\n name: \"Credentials\",\n },\n },\n} as const;\n","export function adminMiddleware(handler: (request: Request) => Promise<Response>) {\n return async (request: Request): Promise<Response> => {\n const sessionCookie = request.headers.get(\"cookie\") ?? \"\";\n const hasSession = sessionCookie.includes(\"next-auth.session-token\");\n\n if (!hasSession) {\n return new Response(JSON.stringify({ error: \"Unauthorized\" }), {\n status: 401,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n return handler(request);\n };\n}\n"],"mappings":"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","names":["collection","jwt","crypto","import_zod","collection","fields","auth","collection","result","slug","serializeConfig","generateAgentToken"]}
@@ -0,0 +1,84 @@
1
+ import { C as CollectionDefinition, A as AdminForgeConfig } from './index-CyzxaE7n.cjs';
2
+ import { D as DbClient } from './client-sRnmZ-Y9.cjs';
3
+ export { adminMiddleware, auth, createAuthConfig } from './auth.cjs';
4
+ import 'zod';
5
+
6
+ /**
7
+ * --- Security Model Definitions ---
8
+ */
9
+ type Action = "create" | "read" | "update" | "delete";
10
+ type AgentTokenPayload = {
11
+ sub: string;
12
+ role: string;
13
+ scope: string[];
14
+ iat: number;
15
+ exp: number;
16
+ iss: "adminforge";
17
+ aud: "agent";
18
+ sessionId: string;
19
+ };
20
+ type AgentSession = AgentTokenPayload;
21
+ type SecurityContext = {
22
+ user?: any;
23
+ agent?: AgentSession;
24
+ source: "user" | "agent";
25
+ };
26
+ /**
27
+ * --- Token Lifecycle ---
28
+ */
29
+ declare function generateAgentToken(userId: string, role: string, scopes: string[], expiresInSeconds?: number): string;
30
+ declare function verifyAgentToken(token: string): AgentTokenPayload;
31
+ declare function assertScope(agent: AgentSession, collection: string, action: Action): void;
32
+
33
+ interface Controller {
34
+ list: (args?: {
35
+ where?: Record<string, unknown>;
36
+ orderBy?: Record<string, string>;
37
+ page?: number;
38
+ pageSize?: number;
39
+ search?: string;
40
+ }) => Promise<{
41
+ data: unknown[];
42
+ total: number;
43
+ page: number;
44
+ pageSize: number;
45
+ }>;
46
+ get: (id: string) => Promise<unknown | null>;
47
+ create: (data: Record<string, unknown>) => Promise<unknown>;
48
+ update: (id: string, data: Record<string, unknown>) => Promise<unknown>;
49
+ delete: (id: string) => Promise<unknown>;
50
+ }
51
+ declare function createController(collection: CollectionDefinition, db: DbClient, session?: SecurityContext): Controller;
52
+
53
+ interface RouteContext {
54
+ params: Promise<Record<string, string>>;
55
+ }
56
+ interface RouteParams {
57
+ config: AdminForgeConfig;
58
+ db: DbClient;
59
+ auth?: any;
60
+ }
61
+ declare function createRouteHandlers({ config, db, auth }: RouteParams): {
62
+ generateHandlers: (collectionName: string) => {
63
+ GET: (request: Request, context: RouteContext) => Promise<Response>;
64
+ POST: (request: Request) => Promise<Response>;
65
+ PATCH: (request: Request, context: RouteContext) => Promise<Response>;
66
+ DELETE: (request: Request, context: RouteContext) => Promise<Response>;
67
+ };
68
+ };
69
+ declare function createAdminForgeApi({ config, db, auth }: RouteParams): {
70
+ GET(request: Request, { params }: {
71
+ params: Promise<any>;
72
+ }): Promise<Response>;
73
+ POST(request: Request, { params }: {
74
+ params: Promise<any>;
75
+ }): Promise<Response>;
76
+ PATCH(request: Request, { params }: {
77
+ params: Promise<any>;
78
+ }): Promise<Response>;
79
+ DELETE(request: Request, { params }: {
80
+ params: Promise<any>;
81
+ }): Promise<Response>;
82
+ };
83
+
84
+ export { type Action, type AgentSession, type AgentTokenPayload, type Controller, type SecurityContext, assertScope, createAdminForgeApi, createController, createRouteHandlers, generateAgentToken, verifyAgentToken };
package/dist/next.d.ts ADDED
@@ -0,0 +1,84 @@
1
+ import { C as CollectionDefinition, A as AdminForgeConfig } from './index-CyzxaE7n.js';
2
+ import { D as DbClient } from './client-D0cjJVsn.js';
3
+ export { adminMiddleware, auth, createAuthConfig } from './auth.js';
4
+ import 'zod';
5
+
6
+ /**
7
+ * --- Security Model Definitions ---
8
+ */
9
+ type Action = "create" | "read" | "update" | "delete";
10
+ type AgentTokenPayload = {
11
+ sub: string;
12
+ role: string;
13
+ scope: string[];
14
+ iat: number;
15
+ exp: number;
16
+ iss: "adminforge";
17
+ aud: "agent";
18
+ sessionId: string;
19
+ };
20
+ type AgentSession = AgentTokenPayload;
21
+ type SecurityContext = {
22
+ user?: any;
23
+ agent?: AgentSession;
24
+ source: "user" | "agent";
25
+ };
26
+ /**
27
+ * --- Token Lifecycle ---
28
+ */
29
+ declare function generateAgentToken(userId: string, role: string, scopes: string[], expiresInSeconds?: number): string;
30
+ declare function verifyAgentToken(token: string): AgentTokenPayload;
31
+ declare function assertScope(agent: AgentSession, collection: string, action: Action): void;
32
+
33
+ interface Controller {
34
+ list: (args?: {
35
+ where?: Record<string, unknown>;
36
+ orderBy?: Record<string, string>;
37
+ page?: number;
38
+ pageSize?: number;
39
+ search?: string;
40
+ }) => Promise<{
41
+ data: unknown[];
42
+ total: number;
43
+ page: number;
44
+ pageSize: number;
45
+ }>;
46
+ get: (id: string) => Promise<unknown | null>;
47
+ create: (data: Record<string, unknown>) => Promise<unknown>;
48
+ update: (id: string, data: Record<string, unknown>) => Promise<unknown>;
49
+ delete: (id: string) => Promise<unknown>;
50
+ }
51
+ declare function createController(collection: CollectionDefinition, db: DbClient, session?: SecurityContext): Controller;
52
+
53
+ interface RouteContext {
54
+ params: Promise<Record<string, string>>;
55
+ }
56
+ interface RouteParams {
57
+ config: AdminForgeConfig;
58
+ db: DbClient;
59
+ auth?: any;
60
+ }
61
+ declare function createRouteHandlers({ config, db, auth }: RouteParams): {
62
+ generateHandlers: (collectionName: string) => {
63
+ GET: (request: Request, context: RouteContext) => Promise<Response>;
64
+ POST: (request: Request) => Promise<Response>;
65
+ PATCH: (request: Request, context: RouteContext) => Promise<Response>;
66
+ DELETE: (request: Request, context: RouteContext) => Promise<Response>;
67
+ };
68
+ };
69
+ declare function createAdminForgeApi({ config, db, auth }: RouteParams): {
70
+ GET(request: Request, { params }: {
71
+ params: Promise<any>;
72
+ }): Promise<Response>;
73
+ POST(request: Request, { params }: {
74
+ params: Promise<any>;
75
+ }): Promise<Response>;
76
+ PATCH(request: Request, { params }: {
77
+ params: Promise<any>;
78
+ }): Promise<Response>;
79
+ DELETE(request: Request, { params }: {
80
+ params: Promise<any>;
81
+ }): Promise<Response>;
82
+ };
83
+
84
+ export { type Action, type AgentSession, type AgentTokenPayload, type Controller, type SecurityContext, assertScope, createAdminForgeApi, createController, createRouteHandlers, generateAgentToken, verifyAgentToken };