{"_id":"@2bbelmiro/web-provider","_rev":"5-d14f8223e89aa67708c3fd93544f0852","name":"@2bbelmiro/web-provider","dist-tags":{"latest":"1.0.29"},"versions":{"1.0.0":{"name":"@2bbelmiro/web-provider","version":"1.0.0","keywords":["provider","state-management","web","angular"],"author":{"name":"Belmiro Miguel"},"license":"MIT","_id":"@2bbelmiro/web-provider@1.0.0","maintainers":[{"name":"2bbelmiro","email":"belmirofranciscomiguel@gmail.com"}],"homepage":"https://github.com/BelmiroMiguel/web-provider#readme","bugs":{"url":"https://github.com/BelmiroMiguel/web-provider/issues"},"dist":{"shasum":"bc8caf198b3b265fca03163a7e65344c3d12b584","tarball":"https://registry.npmjs.org/@2bbelmiro/web-provider/-/web-provider-1.0.0.tgz","fileCount":38,"integrity":"sha512-4t896Wim9KMwhP7GuYMnkamBvNJLnzaEWm/aruFnPk7Aij2Bcvd0p6ySTwYviWq7eDY+d5IEUSisSDVJan0P5Q==","signatures":[{"sig":"MEUCIDmDdxrShXFs/LuU4TjuwiEmrKX8gjpBbJd95HlIOCOgAiEAmSdKcgI5KAYPQ32cIEGRAydsk/pJlR/RiHAInJSgIdk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":72423},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"8c705456522c3e6a183137ee656a181297fe8952","scripts":{"lint":"eslint src tests","test":"vitest run","build":"npm run clean && tsc","clean":"rm -rf dist","test:watch":"vitest","test:package":"npm run build && node -e \"import('./dist/index.js').then(() => console.log('package import ok'))\" && npm pack --dry-run --cache /tmp/npm-cache-web-provider","prepublishOnly":"npm run build"},"_npmUser":{"name":"2bbelmiro","email":"belmirofranciscomiguel@gmail.com"},"repository":{"url":"git+https://github.com/BelmiroMiguel/web-provider.git","type":"git"},"_npmVersion":"10.9.3","description":"Provider para gerenciamento e compartilhamento de estado em aplicações web.","directories":{},"sideEffects":false,"_nodeVersion":"22.18.0","_hasShrinkwrap":false,"devDependencies":{"rxjs":"^7.8.2","tslib":"^2.8.1","eslint":"^9.28.0","vitest":"^3.2.4","@eslint/js":"^9.28.0","typescript":"^5.8.3","@angular/core":"^21.2.17","@angular/common":"^21.2.17","typescript-eslint":"^8.34.0"},"peerDependencies":{"rxjs":">=7.0.0","@angular/core":">=17.0.0"},"_npmOperationalInternal":{"tmp":"tmp/web-provider_1.0.0_1781606106951_0.4594059615317885","host":"s3://npm-registry-packages-npm-production"}},"1.0.8":{"name":"@2bbelmiro/web-provider","version":"1.0.8","keywords":["provider","state-management","web","angular"],"author":{"name":"Belmiro Miguel"},"license":"MIT","_id":"@2bbelmiro/web-provider@1.0.8","maintainers":[{"name":"2bbelmiro","email":"belmirofranciscomiguel@gmail.com"}],"homepage":"https://github.com/BelmiroMiguel/web-provider#readme","bugs":{"url":"https://github.com/BelmiroMiguel/web-provider/issues"},"dist":{"shasum":"556e9254d32a1854460d052fc1ff7945fa14852e","tarball":"https://registry.npmjs.org/@2bbelmiro/web-provider/-/web-provider-1.0.8.tgz","fileCount":42,"integrity":"sha512-XXfkICliRsz2jUt1D/dzpEyymzerUsi67m2T5gUq6L9WUYT8OAepWufjk1BbN3cwHCOmWw4MRNnh0v91nOoqtg==","signatures":[{"sig":"MEYCIQCv9DtIT59Idm3yuqNiOG9cpKwSpQXT9teFwJq4ahZ6hQIhAN7JBJQWVFW4DB54TgB3PsAdPB1frpxP2K+KLHUiAO8B","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":94707},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"8923017f5aaf091f998e0340459cf03272cb4dd9","scripts":{"lint":"eslint src tests","test":"vitest run","build":"npm run clean && tsc","clean":"rm -rf dist","subir":"npm version patch --no-git-tag-version && npm run build && npm publish --access public","test:watch":"vitest","test:package":"npm run build && node -e \"import('./dist/index.js').then(() => console.log('package import ok'))\" && npm pack --dry-run --cache /tmp/npm-cache-web-provider","prepublishOnly":"npm run build","publicar-oficial":"npm --no-git-tag-version version patch && npm run build && npm publish --registry https://npmjs.org --access public"},"_npmUser":{"name":"2bbelmiro","email":"belmirofranciscomiguel@gmail.com"},"repository":{"url":"git+https://github.com/BelmiroMiguel/web-provider.git","type":"git"},"_npmVersion":"11.16.0","description":"Provider para gerenciamento e compartilhamento de estado em aplicações web.","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"rxjs":"^7.8.2","tslib":"^2.8.1","eslint":"^9.28.0","vitest":"^3.2.4","@eslint/js":"^9.28.0","typescript":"^5.8.3","@angular/core":"^21.2.17","@angular/common":"^21.2.17","typescript-eslint":"^8.34.0"},"peerDependencies":{"rxjs":">=7.0.0","@angular/core":">=17.0.0"},"_npmOperationalInternal":{"tmp":"tmp/web-provider_1.0.8_1784533283978_0.1433126840066381","host":"s3://npm-registry-packages-npm-production"}},"1.0.29":{"name":"@2bbelmiro/web-provider","version":"1.0.29","description":"Provider para gerenciamento e compartilhamento de estado em aplicações web.","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"publishConfig":{"registry":"http://localhost:4873"},"scripts":{"clean":"rm -rf dist","build":"npm run clean && tsc","prepublishOnly":"npm run build","lint":"eslint src tests","test":"vitest run","test:package":"npm run build && node -e \"import('./dist/index.js').then(() => console.log('package import ok'))\" && npm pack --dry-run --cache /tmp/npm-cache-web-provider","test:watch":"vitest","subir":"npm version patch --no-git-tag-version && npm run build && npm publish --access public","publicar-oficial":"npm --no-git-tag-version version patch && npm run build && npm publish --registry https://npmjs.org --access public"},"repository":{"type":"git","url":"git+https://github.com/BelmiroMiguel/web-provider.git"},"keywords":["provider","state-management","web","angular"],"author":{"name":"Belmiro Miguel"},"license":"MIT","bugs":{"url":"https://github.com/BelmiroMiguel/web-provider/issues"},"homepage":"https://github.com/BelmiroMiguel/web-provider#readme","peerDependencies":{"@angular/core":">=17.0.0","rxjs":">=7.0.0"},"devDependencies":{"@angular/common":"^21.2.17","@angular/core":"^21.2.17","@eslint/js":"^9.28.0","eslint":"^9.28.0","rxjs":"^7.8.2","tslib":"^2.8.1","typescript":"^5.8.3","typescript-eslint":"^8.34.0","vitest":"^3.2.4"},"sideEffects":false,"gitHead":"749eb47d5ac64006fc6f6fb895aeb9f873442793","_id":"@2bbelmiro/web-provider@1.0.29","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-BiBI2pg+spIKOiCqeNY6JKY6q0LbS5k4LA3XMRIQXvrwHSlCClWK2u1xZeLehkd7uDF9R0nH6fZHiE9kHcNJbg==","shasum":"5a335adcd251e985c24b31c7c2676725bee5af93","tarball":"https://registry.npmjs.org/@2bbelmiro/web-provider/-/web-provider-1.0.29.tgz","fileCount":42,"unpackedSize":98198,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCqN/ouykutgVQsG00cN8YhmYs/s0oBlvGil1Do+9S8pwIgKjfiaTnBZ0QQaBRGylq3SJWGecyLCRNBlaTgRnpbS20="}]},"_npmUser":{"name":"2bbelmiro","email":"belmirofranciscomiguel@gmail.com"},"directories":{},"maintainers":[{"name":"2bbelmiro","email":"belmirofranciscomiguel@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/web-provider_1.0.29_1786585563580_0.7614845612556727"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-16T10:35:06.723Z","modified":"2026-08-13T01:46:03.940Z","0.1.1":"2026-06-16T07:18:49.581Z","1.0.0":"2026-06-16T10:35:07.121Z","1.0.8":"2026-07-20T07:41:24.140Z","1.0.29":"2026-08-13T01:46:03.785Z"},"bugs":{"url":"https://github.com/BelmiroMiguel/web-provider/issues"},"author":{"name":"Belmiro Miguel"},"license":"MIT","homepage":"https://github.com/BelmiroMiguel/web-provider#readme","keywords":["provider","state-management","web","angular"],"repository":{"type":"git","url":"git+https://github.com/BelmiroMiguel/web-provider.git"},"description":"Provider para gerenciamento e compartilhamento de estado em aplicações web.","maintainers":[{"name":"2bbelmiro","email":"belmirofranciscomiguel@gmail.com"}],"readme":"# @2bbelmiro/web-provider\n\nUm provider robusto, reativo e extensível para gerenciamento, compartilhamento e persistência de estado em aplicações Angular de alta performance. Desenvolvido com suporte a Server-Side Rendering (SSR) e estratégias de Hydration.\n\nO `web-provider` permite encapsular regras de negócio em singletons inteligentes, provendo estados reativos de forma transparente.\n\n## 🚀 Principais Recursos\n\n- **Dupla Reatividade Simétrica**: Gerenciamento de estado reativo baseado em RxJS (`WebNotifier`) e em Angular Signals (`WebSignalNotifier`).\n- **Segurança contra Memory Leaks no SSR**: Isolamento de estado nativo por aplicação através de stores em memória autocontidas, eliminando vazamentos de estado cruzado no servidor.\n- **Ciclos de Vida Avançados**: Ganchos internos (`onInit`, `onAccess`) e interceptadores de dados (`shouldUpdateState`, `onBeforeSave`, `onBeforeLoad`) que garantem controle total sobre o fluxo do dado.\n- **Persistência Inteligente & Desacoplada**: Mecanismo interno de persistência via composição (não por herança direta de storage), suportando criptografia, ofuscação ou validações em tempo de gravação/leitura.\n- **Suporte Completo a Zoneless**: Permite a eliminação do Zone.js em projetos modernos usando a reatividade nativa dos Signals.\n- **Injeção de Dependências Fluida**: Acesso nativo ao sistema de DI do Angular através de injeção clássica (`inject`) ou usando o parâmetro unificado `WebRef`.\n\n---\n\n## 📋 Pré-requisitos\n\nCertifique-se de que seu ambiente cumpre os seguintes requisitos mínimos de versão:\n\n- **Node.js**: `18.x` LTS ou superior.\n- **Angular**: `@angular/core` na versão `16.x` ou superior.\n- **RxJS**: `7.x` ou superior.\n\n---\n\n## 🛠️ Instalação\n\nAdicione o pacote ao seu projeto usando seu gerenciador de pacotes:\n\n```bash\nnpm install @2bbelmiro/web-provider\n```\n\n### Dependências de Par (Peer Dependencies)\n\nCaso ainda não as possua instaladas em seu projeto, certifique-se de ter os pacotes principais do Angular:\n\n```bash\nnpm install @angular/core rxjs\n```\n\nSe o seu provider precisar interagir com serviços HTTP, o pacote de serviços comuns é requerido:\n\n```bash\nnpm install @angular/common\n```\n\n---\n\n## ⚙️ Configuração Global\n\nPara instanciar as stores de forma isolada por aplicação, evitar colisões em cenários de renderização no servidor (SSR) e configurar as políticas de persistência padrão, registre o inicializador no arquivo de configuração principal da sua aplicação Angular.\n\n### Inicialização Padrão (`app.config.ts`)\n\n```typescript\nimport { ApplicationConfig } from \"@angular/core\";\nimport { provideWebProviderInitializer } from \"@2bbelmiro/web-provider\";\n\nexport const appConfig: ApplicationConfig = {\n  providers: [provideWebProviderInitializer()],\n};\n```\n\n### Inicialização Customizada (`app.config.ts`)\n\n```typescript\nimport { ApplicationConfig } from \"@angular/core\";\nimport { provideWebProviderInitializer } from \"@2bbelmiro/web-provider\";\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideWebProviderInitializer({\n      storage: {\n        type: \"localStorage\", // Opções: 'localStorage' | 'sessionStorage' | 'memory'\n        prefix: \"my_app_prefix\",\n      },\n      clearStorageOnExpire: true,\n      ttl: 300000, // Tempo de vida padrão: 5 minutos (em milissegundos)\n      zoneChangeDetection: false, // Altere para true se precisar forçar detecção em apps tradicionais com Zone.js\n    }),\n  ],\n};\n```\n\n### Parâmetros de Configuração Global\n\n| Propriedade            | Tipo                                             | Valor Padrão     | Descrição                                                                                  |\n| :--------------------- | :----------------------------------------------- | :--------------- | :----------------------------------------------------------------------------------------- |\n| `storage.type`         | `'localStorage' \\| 'sessionStorage' \\| 'memory'` | `'localStorage'` | O canal físico de persistência dos dados no navegador ou na memória RAM.                   |\n| `storage.prefix`       | `string`                                         | `''`             | Prefixo opcional adicionado às chaves no storage para evitar colisões com outros apps.     |\n| `clearStorageOnExpire` | `boolean`                                        | `false`          | Se `true`, apaga os dados do disco de forma definitiva quando o tempo de expiração expira. |\n| `ttl`                  | `number`                                         | `undefined`      | Tempo de expiração global (Time-To-Live) em milissegundos para as instâncias do provider.  |\n| `zoneChangeDetection`  | `boolean`                                        | `false`          | Quando ativo, aciona a execução do Zone.js para garantir ciclos de renderização com RxJS.  |\n\n---\n\n## 📁 Estrutura de Pastas Sugerida\n\nRecomenda-se organizar os seus providers em diretórios dedicados a domínios de dados ou funcionalidades para manter a manutenibilidade do código:\n\n```text\nsrc/\n├── app/\n│   ├── app.config.ts\n│   ├── app.component.ts\n│   └── core/\n│       └── providers/\n│           ├── auth/\n│           │   ├── auth.interface.ts\n│           │   ├── auth.provider.ts\n│           │   └── auth.provider.spec.ts\n│           └── counter/\n│               ├── counter.interface.ts\n│               └── counter.provider.ts\n```\n\n---\n\n## 💡 Conceitos Fundamentais\n\n```text\nwebProvider\n ├─ Singleton Sob Demanda (Lazy Loading) -> Instanciado apenas no primeiro acesso ou leitura.\n ├─ Persistência Transparente ---------> Gerenciado automaticamente pela biblioteca.\n ├─ Reatividade RxJS (WebNotifier) -------> Fluxos assíncronos e integrados a operadores clássicos.\n ├─ Reatividade Signals (WebSignalNotifier)-> Ideal para arquiteturas modernas Zoneless.\n └─ Isolamento por Aplicação -----------> Totalmente portável e seguro para uso com Angular SSR.\n```\n\n---\n\n## 📖 Como Utilizar\n\n### 1. Usando Estado Reativo com RxJS (`WebNotifier`)\n\nA classe `WebNotifier` é ideal quando sua lógica de negócios necessita de manipulação complexa de fluxos de eventos assíncronos utilizando operadores do RxJS.\n\n#### Criação do Provider (`user.provider.ts`)\n\n```typescript\nimport { webProvider, WebNotifier, WebRef } from \"@2bbelmiro/web-provider\";\n\nexport interface UserState {\n  name: string;\n  logged: boolean;\n  role: \"guest\" | \"user\" | \"admin\";\n}\n\nexport class UserProvider extends WebNotifier<UserState> {\n  constructor() {\n    super({\n      name: \"\",\n      logged: false,\n      role: \"guest\",\n    });\n  }\n\n  login(name: string, role: \"user\" | \"admin\") {\n    this.setState({\n      name: name,\n      logged: true,\n      role: role,\n    });\n  }\n\n  logout() {\n    this.setState({\n      name: \"\",\n      logged: false,\n      role: \"guest\",\n    });\n  }\n}\n\nexport const userProvider = webProvider(\n  \"user_session\",\n  (_ref: WebRef) => new UserProvider(),\n);\n```\n\n#### Consumo no Componente (`user.component.ts`)\n\n```typescript\nimport { Component } from \"@angular/core\";\nimport { CommonModule } from \"@angular/common\";\nimport { userProvider } from \"./user.provider\";\n\n@Component({\n  selector: \"app-user\",\n  standalone: true,\n  imports: [CommonModule],\n  template: `\n    <div *ngIf=\"name$ | async as name; else anonymous\">\n      <p>Olá, {{ name }} (Perfil: {{ userSnapshot.role }})</p>\n      <button (click)=\"onLogout()\">Encerrar Sessão</button>\n    </div>\n    <ng-template #anonymous>\n      <p>Nenhum usuário autenticado no momento.</p>\n      <button (click)=\"onLogin()\">Entrar como Administrador</button>\n    </ng-template>\n  `,\n})\nexport class UserComponent {\n  get userSnapshot() {\n    return userProvider.snapshot;\n  }\n\n  name$ = userProvider.select((state) => state.name);\n\n  onLogin() {\n    userProvider.login(\"Carlos Belmiro\", \"admin\");\n  }\n\n  onLogout() {\n    userProvider.logout();\n  }\n}\n```\n\n---\n\n### 2. Usando Estado Reativo com Angular Signals (`WebSignalNotifier`)\n\nEssa classe é a escolha ideal para aplicações desenvolvidas com foco no Angular moderno e estratégias Zoneless.\n\n#### Criação do Provider (`counter.provider.ts`)\n\n```typescript\nimport { webProvider, WebSignalNotifier } from \"@2bbelmiro/web-provider\";\n\nexport interface CounterState {\n  count: number;\n  lastUpdated: Date | null;\n}\n\nexport class CounterProvider extends WebSignalNotifier<CounterState> {\n  constructor() {\n    super({\n      count: 0,\n      lastUpdated: null,\n    });\n  }\n\n  increment() {\n    this.setState((state) => ({\n      count: state.count + 1,\n      lastUpdated: new Date(),\n    }));\n  }\n\n  reset() {\n    this.setState({\n      count: 0,\n      lastUpdated: null,\n    });\n  }\n}\n\nexport const counterProvider = webProvider(\n  \"counter_state\",\n  () => new CounterProvider(),\n);\n```\n\n#### Consumo no Componente (`counter.component.ts`)\n\n```typescript\nimport { Component } from \"@angular/core\";\nimport { counterProvider } from \"./counter.provider\";\n\n@Component({\n  selector: \"app-counter\",\n  standalone: true,\n  template: `\n    <div>\n      <h3>Contador: {{ count() }}</h3>\n      <p>\n        Última atualização:\n        {{ lastUpdated() ? (lastUpdated() | date: \"mediumTime\") : \"Nunca\" }}\n      </p>\n\n      <button (click)=\"onIncrement()\">Incrementar</button>\n      <button (click)=\"onReset()\">Reiniciar</button>\n    </div>\n  `,\n})\nexport class CounterComponent {\n  count = counterProvider.select((state) => state.count);\n  lastUpdated = counterProvider.select((state) => state.lastUpdated);\n\n  onIncrement() {\n    counterProvider.increment();\n  }\n\n  onReset() {\n    counterProvider.reset();\n  }\n}\n```\n\n---\n\n## 🔄 Ciclos de Vida e Interceptadores\n\nVocê pode estender o comportamento padrão dos seus _providers_ interceptando eventos ou customizando leituras e gravações. Basta sobrescrever os seguintes métodos em sua classe especializada:\n\n```typescript\nimport { WebSignalNotifier } from \"@2bbelmiro/web-provider\";\n\nexport interface PolicyState {\n  policyId: string;\n  premiumValue: number;\n  sensitiveToken: string;\n}\n\nexport class PolicyProvider extends WebSignalNotifier<PolicyState> {\n  constructor() {\n    super({\n      policyId: \"N/A\",\n      premiumValue: 0,\n      sensitiveToken: \"\",\n    });\n  }\n\n  /**\n   * 1. onInit(): Executado imediatamente após a restauração inicial do cache do storage.\n   */\n  protected override onInit(): void {\n    console.log(\"Provider inicializado e estado restaurado a partir do cache.\");\n  }\n\n  /**\n   * 2. onAccess(): Executado toda vez que um componente ou serviço lê ou interage com o provider.\n   * @param isNewInstance Indica se o provider acabou de ser alocado na memória ou se já existia na WebStore.\n   */\n  protected override onAccess(isNewInstance: boolean): void {\n    if (isNewInstance) {\n      console.log(\n        \"Esta é a primeira instância carregada do PolicyProvider (Lazy Loaded).\",\n      );\n    }\n  }\n\n  /**\n   * 3. shouldUpdateState(): Interceptador de mudança de estado em memória.\n   * Retorne \"false\" para abortar a alteração do estado global (rejeição de mutação).\n   */\n  protected override shouldUpdateState(\n    current: PolicyState,\n    next: PolicyState,\n  ): boolean {\n    if (next.premiumValue < 0) {\n      console.warn(\n        \"Operação bloqueada: O valor do prêmio de seguro não pode ser negativo.\",\n      );\n      return false;\n    }\n    return true;\n  }\n\n  /**\n   * 4. onBeforeSave(): Interceptador disparado imediatamente antes de salvar no disco/storage.\n   * Permite alterar o objeto final (ex: criptografia) ou retornar \"false\" para manter o dado apenas em RAM.\n   */\n  protected override onBeforeSave(state: PolicyState): PolicyState | boolean {\n    if (state.policyId === \"N/A\") {\n      return false;\n    }\n\n    return {\n      ...state,\n      sensitiveToken: btoa(state.sensitiveToken),\n    };\n  }\n\n  /**\n   * 5. onBeforeLoad(): Interceptador disparado no momento da leitura/restauração do storage.\n   * Permite decodificar os dados físicos ou rejeitar uma persistência corrompida retornando \"false\".\n   */\n  protected override onBeforeLoad(cached: PolicyState): PolicyState | boolean {\n    try {\n      return {\n        ...cached,\n        sensitiveToken: atob(cached.sensitiveToken),\n      };\n    } catch (e) {\n      console.error(\"Falha ao restaurar cache do storage: Dado corrompido.\");\n      return false;\n    }\n  }\n}\n```\n\n---\n\n## 💉 Injeção de Serviços do Angular\n\nVocê pode injetar serviços Angular nativos no escopo de sua classe através de duas abordagens limpas e em conformidade com as boas práticas do Angular.\n\n### Opção A: Injeção Direta com `inject()` (Recomendado)\n\n```typescript\nimport { inject } from \"@angular/core\";\nimport { HttpClient } from \"@angular/common/http\";\nimport { WebNotifier, webProvider } from \"@2bbelmiro/web-provider\";\n\nexport interface AccountState {\n  users: string[];\n}\n\nexport class AccountProvider extends WebNotifier<AccountState> {\n  private readonly http = inject(HttpClient);\n\n  constructor() {\n    super({ users: [] });\n  }\n\n  loadUsersFromApi() {\n    this.http.get<string[]>(\"/api/users\").subscribe((users) => {\n      this.setState({ users });\n    });\n  }\n}\n\nexport const accountProvider = webProvider(\n  \"account_service\",\n  () => new AccountProvider(),\n);\n```\n\n### Opção B: Injeção por Fábrica com `WebRef`\n\n```typescript\nimport { webProvider, WebRef, WebNotifier } from \"@2bbelmiro/web-provider\";\nimport { MyCustomLoggerService } from \"./my-custom-logger.service\";\n\nexport interface LoggerState {\n  logs: string[];\n}\n\nexport class LoggerProvider extends WebNotifier<LoggerState> {\n  constructor(private readonly loggerService: MyCustomLoggerService) {\n    super({ logs: [] });\n  }\n\n  addLog(message: string) {\n    this.loggerService.logToExternalServer(message);\n    this.setState((state) => ({ logs: [...state.logs, message] }));\n  }\n}\n\nexport const loggerProvider = webProvider(\n  \"application_logger\",\n  (ref: WebRef) => {\n    const loggerService = ref.inject(MyCustomLoggerService);\n    return new LoggerProvider(loggerService);\n  },\n);\n```\n\n---\n\n## 🔗 Comunicação Entre Providers\n\nA comunicação entre múltiplos providers ocorre de maneira nativa e síncrona devido à natureza de singletons autogerenciados da biblioteca:\n\n```typescript\nimport { WebNotifier, webProvider } from \"@2bbelmiro/web-provider\";\nimport { userProvider } from \"./user.provider\";\n\nexport interface AuditState {\n  authorizedActionsCount: number;\n}\n\nexport class AuditProvider extends WebNotifier<AuditState> {\n  constructor() {\n    super({ authorizedActionsCount: 0 });\n  }\n\n  performSecureAction() {\n    const userState = userProvider.snapshot;\n\n    if (userState.logged && userState.role === \"admin\") {\n      this.setState((state) => ({\n        authorizedActionsCount: state.authorizedActionsCount + 1,\n      }));\n      console.log(\"Ação autorizada com sucesso.\");\n    } else {\n      console.error(\"Ação bloqueada: Privilégios insuficientes.\");\n    }\n  }\n}\n\nexport const auditProvider = webProvider(\n  \"audit_monitor\",\n  () => new AuditProvider(),\n);\n```\n\n---\n\n## 💾 Persistência e Estratégia de Storage por Composição\n\nA biblioteca disponibiliza a utilidade `WebLocalStorage` para operações isoladas de persistência que adotam os prefixos e configurações estabelecidas no inicializador global. O acesso a essa estrutura é feito por meio de **composição**, garantindo desacoplamento e facilitando a escrita de testes unitários.\n\n### Utilizando `WebLocalStorage` através de Composição\n\n```typescript\nimport { webProvider, WebRef, WebLocalStorage } from \"@2bbelmiro/web-provider\";\n\nexport interface DraftState {\n  content: string;\n}\n\nexport class DraftProvider {\n  constructor(private readonly storage: WebLocalStorage) {}\n\n  saveDraft(value: string) {\n    this.storage.setItem(\"user_draft_key\", value);\n  }\n\n  getDraft(): string {\n    return this.storage.getItem<string>(\"user_draft_key\") || \"\";\n  }\n\n  clearDraft() {\n    this.storage.removeItem(\"user_draft_key\");\n  }\n}\n\nexport const draftProvider = webProvider(\"draft_manager\", (ref: WebRef) => {\n  const storageService = ref.inject(WebLocalStorage);\n  return new DraftProvider(storageService);\n});\n```\n\n### Qual Tipo de Storage Utilizar?\n\n| Estratégia de Storage | Armazenamento           | Ciclo de Vida do Dado                                                          |\n| :-------------------- | :---------------------- | :----------------------------------------------------------------------------- |\n| `localStorage`        | Persistido no Navegador | Vitalício até que seja excluído manualmente por limpeza ou comandos do código. |\n| `sessionStorage`      | Persistido no Navegador | Excluído de forma automática no fechamento da aba ou janela do browser.        |\n| `memory`              | Armazenamento em RAM    | Mantido apenas enquanto a página atual não for totalmente recarregada.         |\n\n---\n\n## 🕰️ Configuração de TTL (Time-To-Live)\n\nVocê pode aplicar tempos limites de retenção de dados especificamente por instâncias de providers individuais:\n\n```typescript\nimport { webProvider, WebSignalNotifier } from \"@2bbelmiro/web-provider\";\n\nexport interface TempSessionState {\n  oneTimeToken: string;\n}\n\nexport class TempSessionProvider extends WebSignalNotifier<TempSessionState> {\n  constructor() {\n    super({ oneTimeToken: \"\" });\n  }\n}\n\nexport const tempSessionProvider = webProvider(\n  \"temporary_session\",\n  () => new TempSessionProvider(),\n  {\n    ttl: 60000,\n    clearStorageOnExpire: true,\n  },\n);\n```\n\n---\n\n## 🎛️ Referência da API Pública\n\n| Assinatura                               | Tipo        | Descrição                                                                                        |\n| :--------------------------------------- | :---------- | :----------------------------------------------------------------------------------------------- |\n| `webProvider(key, factory, options?)`    | `Function`  | Registra e recupera de forma preguiçosa um provider singleton a partir da chave única fornecida. |\n| `provideWebProviderInitializer(config?)` | `Function`  | Função de bootstrap obrigatória para configurar o ciclo de vida e evitar colisões em SSR.        |\n| `WebNotifier<T>`                         | `Class`     | Classe abstrata base para estados orientados a RxJS Observables.                                 |\n| `WebSignalNotifier<T>`                   | `Class`     | Classe abstrata base para estados orientados ao novo sistema de Angular Signals.                 |\n| `WebRef`                                 | `Interface` | Objeto de referência enviado nas fábricas para resolução pontual de dependências Angular.        |\n| `WebLocalStorage`                        | `Class`     | Classe utilitária que unifica o acesso ao storage local utilizando o prefixo global do app.      |\n| `destroyProvider(key)`                   | `Function`  | Desaloca da memória RAM o provider referenciado e força sua reinicialização no próximo acesso.   |\n\n---\n\n## 🖥️ Scripts do Projeto\n\nOs seguintes comandos estão disponíveis para execução de rotinas no ecossistema de desenvolvimento da biblioteca:\n\n| Comando                | Função                                                                                                     |\n| :--------------------- | :--------------------------------------------------------------------------------------------------------- |\n| `npm run build`        | Transpila o código-fonte TypeScript da pasta `src` gerando a distribuição final otimizada na pasta `dist`. |\n| `npm test`             | Inicia o executor de testes automatizados e suítes unitárias utilizando o motor do Vitest.                 |\n| `npm run lint`         | Executa a varredura estática de formatação e análise lógica de código por meio do ESLint.                  |\n| `npm run test:package` | Cria o artefato local (.tgz) simulando uma distribuição limpa para validações em ambientes de sandbox.     |\n\n---\n\n## 📄 Licença\n\nDistribuído sob a licença **MIT**. Consulte o arquivo `LICENSE` na raiz do repositório para obter mais detalhes.\n","readmeFilename":"README.md"}