{"_id":"@biks2013/config-service","_rev":"3-d4c0bc2111cda34cc63d8b9c0859f50d","name":"@biks2013/config-service","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@biks2013/config-service","version":"1.0.0","license":"MIT","_id":"@biks2013/config-service@1.0.0","maintainers":[{"name":"giorgos-marinos","email":"giorgos.marinos@gmail.com"}],"dist":{"shasum":"9747fd9677279a79737b05b06e23fe3a8879d914","tarball":"https://registry.npmjs.org/@biks2013/config-service/-/config-service-1.0.0.tgz","fileCount":21,"integrity":"sha512-TV6LmDtyVjPubXzHmuiuKO1XghFRvLCTCoIwslwTzB1VsyDU3Hss/HWXgD1TcFvhgoZUpfh4CS/JJS+PtmKblQ==","signatures":[{"sig":"MEQCIFVyIf93MvzySx2XiSAMJlMVDdsBNgPz8q1XO0gwlvvJAiAkVhtSqJWspvrWrze12k8WtJrsl0KkSz6Fel2w85klrg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":55882},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"8c424647d7f1e6bbd6d881bb419c11ba455d1176","scripts":{"lint":"eslint . --ext .ts","test":"jest","build":"tsc -p tsconfig.json","clean":"rm -rf dist coverage","typecheck":"tsc --noEmit"},"_npmUser":{"name":"giorgos-marinos","actor":{"name":"giorgos-marinos","type":"user","email":"giorgos.marinos@gmail.com"},"email":"giorgos.marinos@gmail.com"},"_npmVersion":"10.9.2","description":"Configuration service with multi-source fallback pattern","directories":{},"_nodeVersion":"23.5.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.2","typescript":"^5.4.3","@types/jest":"^29.5.12","@types/node":"^20.11.30"},"peerDependencies":{"@types/node":">=18","@biks2013/asset-database":"^1.0.0","@biks2013/github-asset-client":"^1.0.0"},"peerDependenciesMeta":{"@biks2013/asset-database":{"optional":true},"@biks2013/github-asset-client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/config-service_1.0.0_1750872953621_0.7948294831287925","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@biks2013/config-service","version":"1.0.1","license":"MIT","_id":"@biks2013/config-service@1.0.1","maintainers":[{"name":"giorgos-marinos","email":"giorgos.marinos@gmail.com"}],"dist":{"shasum":"985807f907632c04b234659b64ef8fee1baa43d5","tarball":"https://registry.npmjs.org/@biks2013/config-service/-/config-service-1.0.1.tgz","fileCount":21,"integrity":"sha512-zO2BxRfCUN0uxdkDpamfxDTyeveXldYlm3EFT3Oig9vihuyK7/sU94m0uMiLfArnoDO1Yol2Ba4mjY8/ujiDvA==","signatures":[{"sig":"MEUCIFUG86V4gnBQcjBkAu+S7ahnLIh5gzLh+Lz+kE9V1RWYAiEAvwKKCWGSneHo057wIAR+vdpjlC6TuLTigJa7Nn93ng0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":64961},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"3849a10639eca910d3cb0ef9ccfd8ab8a3374757","scripts":{"lint":"eslint . --ext .ts","test":"jest","build":"tsc -p tsconfig.json","clean":"rm -rf dist coverage","typecheck":"tsc --noEmit"},"_npmUser":{"name":"giorgos-marinos","actor":{"name":"giorgos-marinos","type":"user","email":"giorgos.marinos@gmail.com"},"email":"giorgos.marinos@gmail.com"},"_npmVersion":"10.9.2","description":"Configuration service with multi-source fallback pattern","directories":{},"_nodeVersion":"23.11.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.2","typescript":"^5.4.3","@types/jest":"^29.5.12","@types/node":"^20.11.30"},"peerDependencies":{"@types/node":">=18","@biks2013/asset-database":"^1.0.1","@biks2013/github-asset-client":"^1.0.1"},"peerDependenciesMeta":{"@biks2013/asset-database":{"optional":true},"@biks2013/github-asset-client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/config-service_1.0.1_1750925626828_0.9096021356479589","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@biks2013/config-service","version":"1.0.2","description":"Configuration service with multi-source fallback pattern","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc -p tsconfig.json","test":"jest","lint":"eslint . --ext .ts","clean":"rm -rf dist coverage","typecheck":"tsc --noEmit"},"dependencies":{},"devDependencies":{"@types/jest":"^29.5.12","@types/node":"^20.11.30","jest":"^29.7.0","ts-jest":"^29.1.2","typescript":"^5.4.3"},"peerDependencies":{"@biks2013/github-asset-client":"^1.0.1","@biks2013/asset-database":"^1.0.1","@types/node":">=18"},"peerDependenciesMeta":{"@biks2013/github-asset-client":{"optional":true},"@biks2013/asset-database":{"optional":true}},"publishConfig":{"access":"public"},"license":"MIT","_id":"@biks2013/config-service@1.0.2","gitHead":"f5600780d833f3038dbf0cbd5f11f2bfd6e962fb","_nodeVersion":"23.11.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-NmT7ZCcyO19Jb25/M3V9o/gJXlVvdded+A6Hv2YjGCZT9d5EAFuogD4s5pnx9VgrN6I5KBjk/OP9eVK/uJRyUg==","shasum":"b3e3d45aac47e8f136f571f9dbb81ad28dbc4abf","tarball":"https://registry.npmjs.org/@biks2013/config-service/-/config-service-1.0.2.tgz","fileCount":21,"unpackedSize":64961,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDXOFtxO3qi3tsdtphXfWKtHKseVIn3JipM9qgod7knfwIgBt+UCpamaho83YQsmdcFIrqX37LxDST46UM1OeDLfRs="}]},"_npmUser":{"name":"giorgos-marinos","email":"giorgos.marinos@gmail.com"},"directories":{},"maintainers":[{"name":"giorgos-marinos","email":"giorgos.marinos@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/config-service_1.0.2_1752189094509_0.6709314866893974"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-25T17:35:53.445Z","modified":"2025-07-10T23:11:34.910Z","1.0.0":"2025-06-25T17:35:53.832Z","1.0.1":"2025-06-26T08:13:47.038Z","1.0.2":"2025-07-10T23:11:34.689Z"},"license":"MIT","description":"Configuration service with multi-source fallback pattern","maintainers":[{"name":"giorgos-marinos","email":"giorgos.marinos@gmail.com"}],"readme":"# @biks2013/config-service\n\nConfiguration service with multi-source fallback pattern, type safety, and hot reload support.\n\n## Installation\n\n```bash\nnpm install @biks2013/config-service\n```\n\n## Features\n\n- 🔄 GitHub-first configuration with automatic database fallback\n- 📦 Support for GitHub (primary) and Database (fallback) sources\n- 🔒 Type-safe configuration with TypeScript generics\n- 💾 Automatic caching from GitHub to Database\n- 🏗️ Extensible architecture for custom configuration services\n- 🚫 Returns null when configuration not found in any source\n- 🛡️ Resilient operation when GitHub is unavailable\n\n## Usage\n\n### Basic Example\n\n```typescript\nimport { createConfigService } from '@biks2013/config-service';\nimport { GitHubAssetClient } from '@biks2013/github-asset-client';\nimport { AssetDatabaseService } from '@biks2013/asset-database';\nimport * as YAML from 'yaml';\n\ninterface AppConfig {\n  database: {\n    host: string;\n    port: number;\n  };\n  features: {\n    enableCache: boolean;\n  };\n}\n\nconst configService = createConfigService<AppConfig>({\n  sources: [\n    {\n      type: 'github',\n      priority: 1,  // Primary source - always tried first\n      options: {\n        client: new GitHubAssetClient({\n          repo: 'org/config-repo',\n          token: process.env.GITHUB_TOKEN!,\n        }),\n        assetKey: 'config/app.yaml',\n      },\n    },\n    {\n      type: 'database',\n      priority: 2,  // Fallback - only used if GitHub fails\n      options: {\n        service: new AssetDatabaseService({\n          connectionString: process.env.DATABASE_URL!,\n          ownerCategory: 'app',\n          ownerKey: 'my-app',\n        }),\n        assetKey: 'app-config',\n      },\n    },\n  ],\n  parser: async (content) => YAML.parse(content),\n}, (service, data) => {\n  // Process the parsed configuration\n  // Note: configs is protected, processing handled internally\n});\n\n// Use the service\nconst service = configService();\n\n// Get specific config values\nconst dbHost = await service.getConfig('database.host');\nif (dbHost === null) {\n  console.log('Configuration not found - GitHub unavailable and no cached version in database');\n  return;\n}\n\nconst cacheEnabled = await service.getConfig('features.enableCache');\n\n// Get all configuration\nconst allConfig = await service.getAll();\n\n// Reload configuration\nawait service.reload();\n\n// Clean up\nawait service.destroy();\n```\n\n### Custom Configuration Service\n\n```typescript\nimport { ConfigService, createConfigService } from '@biks2013/config-service';\n\ninterface UserPermissions {\n  userId: string;\n  permissions: string[];\n}\n\nclass PermissionService extends ConfigService<UserPermissions[]> {\n  private permissions = new Map<string, string[]>();\n\n  protected processConfiguration(data: UserPermissions[]): void {\n    this.permissions.clear();\n    for (const user of data) {\n      this.permissions.set(user.userId, user.permissions);\n    }\n  }\n\n  async getUserPermissions(userId: string): Promise<string[]> {\n    await this.ensureInitialized();\n    return this.permissions.get(userId) || [];\n  }\n\n  async hasPermission(userId: string, permission: string): Promise<boolean> {\n    const permissions = await this.getUserPermissions(userId);\n    return permissions.includes(permission);\n  }\n}\n```\n\n## Configuration Sources\n\n### GitHub Source\n\n```typescript\n{\n  type: 'github',\n  priority: 1,\n  options: {\n    client: GitHubAssetClient,\n    assetKey: 'path/to/config.yaml'\n  }\n}\n```\n\n### Database Source\n\n```typescript\n{\n  type: 'database',\n  priority: 2,\n  options: {\n    service: AssetDatabaseService,\n    assetKey: 'config-key',\n    category: 'optional-category'\n  }\n}\n```\n\n\n\n## API\n\n### `createConfigService<T>(options, processor)`\n\nCreates a singleton configuration service instance.\n\n#### Options\n\n```typescript\ninterface ConfigServiceOptions<T> {\n  sources: ConfigSource[];           // Configuration sources with priorities\n  parser: (content: string) => T;    // Parser function (e.g., JSON.parse, YAML.parse)\n  verbose?: boolean;                 // Enable detailed logging (default: false)\n}\n```\n\n#### Processor Function\n\n```typescript\ntype ConfigProcessor<T> = (service: ConfigService<T>, data: T) => void;\n```\n\n### ConfigService Methods\n\n- `getConfig(key?: string): Promise<any>` - Get configuration value by key (returns null if not found)\n- `getAll(): Promise<Map<string, any>>` - Get all configuration values\n- `reload(): Promise<void>` - Reload configuration from sources\n- `destroy(): Promise<void>` - Clean up resources\n\n## Configuration Loading Strategy\n\nThe service follows a GitHub-first approach with database fallback:\n\n1. **Primary Source (GitHub)**: Always attempted first\n   - Fetches latest configuration from GitHub repository\n   - On success: Automatically caches to database for future fallback\n   - On failure: Falls back to database cache\n\n2. **Fallback Source (Database)**: Only used when GitHub is unavailable\n   - Provides resilience during GitHub outages\n   - Contains previously cached configurations\n   - Never accessed directly unless GitHub fails\n\n3. **Returns `null`**: When configuration not found in any source\n\nThis ensures you always get the latest configuration when possible, with automatic failover for reliability.\n\n## Verbose Logging\n\nEnable verbose mode to get detailed insights into the configuration loading process:\n\n```typescript\nconst configService = createConfigService<AppConfig>({\n  sources: [...],\n  parser: YAML.parse,\n  verbose: true  // Enable verbose logging\n}, processor);\n```\n\nWhen verbose mode is enabled, you'll see:\n\n1. **GitHub Reads**: Detailed information about assets read from GitHub\n   - Asset path being read\n   - File size and SHA\n   - Content preview\n\n2. **Database Operations**: \n   - Asset registration logs\n   - Content length and creation timestamps\n   - **Difference Detection**: Automatic comparison between GitHub and cached versions\n\n3. **Fallback Behavior**: Clear logs showing which source was attempted and why it failed\n\nExample verbose output:\n```\n[ConfigService] Starting configuration reload...\n[GitHub] Reading asset from path: config/app.yaml\n[GitHub] Successfully read asset 'config/app.yaml':\n[GitHub]   - Size: 1234 bytes\n[GitHub]   - SHA: abc123def456...\n[GitHub]   - Content preview: database:\\n  host: localhost\\n  port: 5432\\n...\n[Database] Registering asset 'app-config' in database\n[Database] DIFFERENCE DETECTED: Content from GitHub differs from database cache\n[Database]   - Previous length: 1200 bytes\n[Database]   - New length: 1234 bytes\n[Database] Successfully registered asset 'app-config' in database\n[ConfigService] Configuration loaded successfully from github:config/app.yaml\n```\n\nThis is especially useful for:\n- Debugging configuration issues\n- Monitoring configuration changes\n- Understanding fallback behavior\n- Tracking cache updates\n\n## License\n\nMIT","readmeFilename":"README.md"}