UNPKG

@seed-fe/permission

Version:

Framework-agnostic permission management library with batching, caching, and debouncing

1 lines 17.9 kB
{"version":3,"sources":["../src/constants/index.ts","../src/utils/permissionUtils.ts","../src/core/permissionBatchManager.ts","../src/config/configurePermission.ts","../src/utils/permission.ts"],"names":["PACKAGE_NAME","BATCH_CONFIG","CACHE_CONFIG","PERMISSION_CHECK_MODES","PERMISSION_BATCH_ENDPOINT","PermissionError","message","packageName","permissionConfig","originalError","normalizePermissionConfig","permission","config","normalizePermissionResult","result","normalizePermissionResults","results","createPermissionCacheKey","createPermissionError","globalPermissionService","defaultOptions","batchPermissionCheck","registerPermissionService","service","options","mergedOptions","createBatchRequest","configs","checkPermission","customService","error","clearPermissionCache","getPermissionStats","configurePermission"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Package name constant - used for exception handling\n */\nexport const PACKAGE_NAME = '@seed-fe/permission';\n\n/**\n * Default permission batch processing configuration\n */\nexport const BATCH_CONFIG = {\n /** Batch processing delay time (milliseconds) */\n DELAY: 50,\n /** Maximum batch size */\n MAX_SIZE: 100,\n};\n\n/**\n * Default cache configuration\n */\nexport const CACHE_CONFIG = {\n /** Whether to enable caching */\n ENABLE: false,\n /** Cache TTL (milliseconds) - 5 minutes */\n TTL: 300000,\n};\n\n/**\n * Permission check modes - defines how multiple permissions are evaluated\n */\nexport const PERMISSION_CHECK_MODES = {\n /** All permissions must be satisfied */\n ALL: 'all',\n /** Any one permission needs to be satisfied */\n ANY: 'any',\n} as const;\n\n/**\n * Permission batch processing endpoint identifier\n */\nexport const PERMISSION_BATCH_ENDPOINT = 'permission-batch';\n","import { PERMISSION_CHECK_MODES } from '../constants';\nimport type { PermissionConfig, PermissionInput, PermissionResult } from '../types';\n\n/**\n * Permission error class\n *\n * Exception class specially designed for @seed-fe/exception-handler\n * Contains package name information for special handling by global exception handler\n */\nexport class PermissionError extends Error {\n constructor(\n message: string,\n public readonly packageName: string,\n public readonly permissionConfig?: PermissionConfig,\n public readonly originalError?: unknown\n ) {\n super(message);\n this.name = 'PermissionError';\n }\n}\n\n/**\n * Normalize permission input to standardized PermissionConfig format\n *\n * Converts various permission input formats (string, string array, or PermissionConfig)\n * into a consistent PermissionConfig object with default values applied.\n *\n * @param {PermissionInput} permission - Permission input in any supported format\n * @returns {PermissionConfig} Normalized permission configuration with default mode and optional biz params\n *\n * @example\n * ```typescript\n * // String input\n * normalizePermissionConfig('user.edit')\n * // Returns: { code: 'user.edit', mode: 'all' }\n *\n * // Array input\n * normalizePermissionConfig(['user.edit', 'user.delete'])\n * // Returns: { code: ['user.edit', 'user.delete'], mode: 'all' }\n *\n * // Full config (returned as-is)\n * normalizePermissionConfig({ code: 'user.edit', mode: 'any', biz: { userId: '123' } })\n * // Returns: { code: 'user.edit', mode: 'any', biz: { userId: '123' } }\n * ```\n */\nexport function normalizePermissionConfig(permission: PermissionInput): PermissionConfig {\n if (typeof permission === 'string') {\n return { code: permission, mode: PERMISSION_CHECK_MODES.ALL };\n }\n\n if (Array.isArray(permission)) {\n return { code: permission, mode: PERMISSION_CHECK_MODES.ALL };\n }\n\n // At this point, permission must be PermissionConfig\n const config = permission as PermissionConfig;\n\n return {\n code: config.code,\n mode: config.mode || PERMISSION_CHECK_MODES.ALL,\n biz: config.biz,\n };\n}\n\n/**\n * Normalize permission result to boolean format\n *\n * Converts permission service results from various formats (boolean or number)\n * to a standardized boolean value. Supports both boolean and numeric (0/1) results.\n *\n * @param {PermissionResult} result - Permission result from service (boolean or number)\n * @returns {boolean} Normalized boolean result (true = has permission, false = no permission)\n *\n * @example\n * ```typescript\n * // Boolean inputs\n * normalizePermissionResult(true) // Returns: true\n * normalizePermissionResult(false) // Returns: false\n *\n * // Numeric inputs (commonly used by some backend APIs)\n * normalizePermissionResult(1) // Returns: true\n * normalizePermissionResult(0) // Returns: false\n * ```\n */\nexport function normalizePermissionResult(result: PermissionResult): boolean {\n if (typeof result === 'boolean') {\n return result;\n }\n\n if (typeof result === 'number') {\n return result === 1;\n }\n\n return false;\n}\n\n/**\n * Batch normalize permission results\n */\nexport function normalizePermissionResults(results: PermissionResult[]): boolean[] {\n return results.map((result) => normalizePermissionResult(result));\n}\n\n/**\n * Create permission cache key\n */\nexport function createPermissionCacheKey(config: PermissionConfig): string {\n return JSON.stringify({\n code: Array.isArray(config.code) ? [...config.code].sort() : config.code,\n mode: config.mode || PERMISSION_CHECK_MODES.ALL,\n biz: config.biz || {},\n });\n}\n\n/**\n * Create permission error and throw\n *\n * Simplified exception creation function that only creates exceptions without handling\n * Exceptions will be globally caught and handled by @seed-fe/exception-handler\n */\nexport function createPermissionError(\n message: string,\n packageName: string,\n config?: PermissionConfig,\n originalError?: unknown\n): PermissionError {\n return new PermissionError(message, packageName, config, originalError);\n}\n","import { createBatchRequest } from '@seed-fe/batch-request';\nimport {\n BATCH_CONFIG,\n CACHE_CONFIG,\n PACKAGE_NAME,\n PERMISSION_BATCH_ENDPOINT,\n PERMISSION_CHECK_MODES,\n} from '../constants';\nimport type { PermissionConfig, PermissionResult, PermissionServiceFn, PermissionServiceOptions } from '../types';\nimport { createPermissionError, normalizePermissionResult } from '../utils/permissionUtils';\n\n/**\n * Global permission service\n */\nlet globalPermissionService: PermissionServiceFn | null = null;\n\n/**\n * Default permission service configuration\n */\nconst defaultOptions: Required<PermissionServiceOptions> = {\n batch: {\n delay: BATCH_CONFIG.DELAY,\n maxSize: BATCH_CONFIG.MAX_SIZE,\n },\n cache: {\n enable: CACHE_CONFIG.ENABLE,\n ttl: CACHE_CONFIG.TTL,\n },\n};\n\n/**\n * Batch permission check function\n */\nlet batchPermissionCheck: ((permission: PermissionConfig) => Promise<boolean>) | null = null;\n\n/**\n * Create cache key\n */\nfunction createPermissionCacheKey(config: PermissionConfig): string {\n return JSON.stringify({\n code: Array.isArray(config.code) ? [...config.code].sort() : config.code,\n mode: config.mode || PERMISSION_CHECK_MODES.ALL,\n biz: config.biz || {},\n });\n}\n\n/**\n * Permission result normalization\n */\nfunction normalizePermissionResults(results: PermissionResult[]): boolean[] {\n return results.map((result) => normalizePermissionResult(result));\n}\n\n/**\n * Register permission service\n */\nexport function registerPermissionService(service: PermissionServiceFn, options: PermissionServiceOptions = {}): void {\n globalPermissionService = service;\n\n // Merge configuration\n const mergedOptions: Required<PermissionServiceOptions> = {\n batch: { ...defaultOptions.batch, ...options.batch },\n cache: { ...defaultOptions.cache, ...options.cache },\n };\n\n // Create batch processing function\n batchPermissionCheck = createBatchRequest({\n endpoint: PERMISSION_BATCH_ENDPOINT,\n service: async (configs: PermissionConfig[]) => {\n const results = await service(configs);\n return normalizePermissionResults(results);\n },\n batch: mergedOptions.batch,\n cache: mergedOptions.cache,\n cacheKey: createPermissionCacheKey,\n });\n}\n\n/**\n * Check permission\n */\nexport async function checkPermission(\n permission: PermissionConfig,\n customService?: PermissionServiceFn\n): Promise<boolean> {\n try {\n // Use custom service\n if (customService) {\n const configs = [permission];\n const results = await customService(configs);\n return normalizePermissionResult(results[0]);\n }\n\n // Use global service\n if (!batchPermissionCheck) {\n // Throw exception, let global exception handler handle\n throw createPermissionError('[@seed-fe/permission] Permission service not registered', PACKAGE_NAME, permission);\n }\n\n return await batchPermissionCheck(permission);\n } catch (error) {\n // If it's PermissionError, throw directly\n if (error instanceof Error && error.name === 'PermissionError') {\n throw error;\n }\n\n // Wrap other errors as PermissionError and throw\n throw createPermissionError('[@seed-fe/permission] Permission check failed', PACKAGE_NAME, permission, error);\n }\n}\n\n/**\n * Clear permission cache by reinitializing the batch processing system\n *\n * Note: This function clears cache by recreating the entire batch processing function,\n * which ensures all cached results are discarded. This approach is used because\n * the cache is managed internally by @seed-fe/batch-request.\n *\n * @example\n * ```typescript\n * // Clear cache when user logs out\n * function handleLogout() {\n * clearPermissionCache();\n * // ... other logout logic\n * }\n * ```\n */\nexport function clearPermissionCache(): void {\n if (batchPermissionCheck) {\n // Clear cache by recreating batch processing function\n if (globalPermissionService) {\n registerPermissionService(globalPermissionService);\n }\n }\n}\n\n/**\n * Get permission system status information\n *\n * Returns current state of the permission management system, including\n * service registration status and batch processing availability.\n *\n * @returns {object} Permission system status\n * @returns {boolean} returns.hasGlobalService - Whether a global permission service is registered\n * @returns {boolean} returns.hasBatchFunction - Whether batch processing function is available\n *\n * @example\n * ```typescript\n * const status = getPermissionStats();\n * console.log('Service registered:', status.hasGlobalService);\n * console.log('Batch processing ready:', status.hasBatchFunction);\n *\n * // Check system readiness\n * if (!status.hasGlobalService) {\n * console.warn('Permission service not registered');\n * }\n * ```\n */\nexport function getPermissionStats() {\n return {\n hasGlobalService: !!globalPermissionService,\n hasBatchFunction: !!batchPermissionCheck,\n };\n}\n","import { registerPermissionService } from '../core/permissionBatchManager';\nimport type { PermissionServiceFn, PermissionServiceOptions } from '../types';\n\n/**\n * Global permission configuration interface\n */\nexport interface GlobalPermissionConfig {\n /** Permission check service function */\n permissionService: PermissionServiceFn;\n /** Permission service configuration options */\n permissionServiceOptions?: PermissionServiceOptions;\n}\n\n/**\n * Configure global permission service\n *\n * Provides a convenient way to configure global permission service\n *\n * @param config Permission configuration\n *\n * @example\n * ```typescript\n * import { configurePermission } from '@seed-fe/permission';\n *\n * configurePermission({\n * permissionService: async (configs) => {\n * const response = await fetch('/api/permissions/check', {\n * method: 'POST',\n * body: JSON.stringify(configs)\n * });\n * return response.json();\n * },\n * permissionServiceOptions: {\n * batch: { delay: 50, maxSize: 100 },\n * cache: { enable: true, ttl: 300000 } // IMPORTANT: Explicitly enable caching (default is false)\n * }\n * });\n * ```\n */\nexport function configurePermission(config: GlobalPermissionConfig): void {\n registerPermissionService(config.permissionService, config.permissionServiceOptions);\n}\n","import { checkPermission as coreCheckPermission } from '../core/permissionBatchManager';\nimport type { PermissionInput, PermissionServiceFn } from '../types';\nimport { normalizePermissionConfig } from './permissionUtils';\n\n/**\n * Permission check function\n *\n * Provides imperative permission checking capability based on global permission manager.\n * Supports batch processing and caching, suitable for permission judgment in business logic.\n *\n * Exception handling:\n * - All exceptions will throw PermissionError\n * - Exceptions will be globally caught by @seed-fe/exception-handler\n * - Exceptions are not handled internally within this function\n *\n * @param permission Permission configuration\n * @param customService Optional custom permission service\n * @returns Promise<boolean> Permission check result\n * @throws {PermissionError} Throws exception when permission check fails\n *\n * @example\n * ```typescript\n * // Check single permission (using example permission codes)\n * const canEdit = await checkPermission('user.edit');\n *\n * // Check multiple permissions (all must be satisfied)\n * const canManage = await checkPermission({\n * code: ['user.edit', 'user.delete'],\n * mode: 'all'\n * });\n *\n * // Check multiple permissions (any one satisfied)\n * const hasAnyPermission = await checkPermission({\n * code: ['admin.panel', 'user.manage'],\n * mode: 'any'\n * });\n *\n * // Check with business context\n * const canEditDocument = await checkPermission({\n * code: 'document.edit',\n * biz: { documentId: '123', ownerId: 'user456' }\n * });\n * ```\n *\n * Note: Permission codes like 'user.edit', 'admin.panel' are examples.\n * Replace them with your actual permission codes from your system.\n */\nexport async function checkPermission(\n permission: PermissionInput,\n customService?: PermissionServiceFn\n): Promise<boolean> {\n const config = normalizePermissionConfig(permission);\n // Directly call core check function, let exceptions bubble up\n return coreCheckPermission(config, customService);\n}\n"]}