@the-bearded-bear/claude-craft 8.8.1 → 8.8.2

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 (79) hide show
  1. package/Dev/i18n/de/Angular/commands/check-compliance.md +218 -168
  2. package/Dev/i18n/de/Common/agents/refactoring-specialist.md +146 -69
  3. package/Dev/i18n/de/Common/commands/add-technology.md +166 -68
  4. package/Dev/i18n/de/Common/commands/setup-ci.md +216 -33
  5. package/Dev/i18n/de/Laravel/commands/check-compliance.md +223 -115
  6. package/Dev/i18n/de/Python/checklists/new-feature.md +319 -44
  7. package/Dev/i18n/de/React/rules/02-architecture.md +483 -322
  8. package/Dev/i18n/de/React/rules/03-coding-standards.md +584 -368
  9. package/Dev/i18n/de/Symfony/commands/check-compliance.md +186 -114
  10. package/Dev/i18n/de/Symfony/rules/07-testing-symfony.md +679 -10
  11. package/Dev/i18n/de/UIUX/commands/a11y-component.md +284 -26
  12. package/Dev/i18n/de/UIUX/commands/design-tokens.md +199 -35
  13. package/Dev/i18n/de/UIUX/commands/user-flow.md +179 -16
  14. package/Dev/i18n/de/VueJS/commands/check-compliance.md +227 -102
  15. package/Dev/i18n/es/Angular/commands/check-compliance.md +217 -167
  16. package/Dev/i18n/es/Common/commands/add-technology.md +158 -60
  17. package/Dev/i18n/es/Laravel/commands/check-compliance.md +223 -115
  18. package/Dev/i18n/es/React/commands/check-testing.md +263 -169
  19. package/Dev/i18n/es/ReactNative/commands/check-testing.md +256 -198
  20. package/Dev/i18n/es/Symfony/commands/check-compliance.md +189 -117
  21. package/Dev/i18n/es/Symfony/commands/check-testing.md +301 -102
  22. package/Dev/i18n/es/Symfony/commands/migration-plan.md +267 -34
  23. package/Dev/i18n/es/UIUX/commands/a11y-component.md +274 -16
  24. package/Dev/i18n/es/UIUX/commands/design-tokens.md +186 -22
  25. package/Dev/i18n/es/UIUX/commands/user-flow.md +173 -10
  26. package/Dev/i18n/es/VueJS/commands/check-compliance.md +227 -102
  27. package/Dev/i18n/fr/Angular/commands/check-compliance.md +217 -167
  28. package/Dev/i18n/fr/Common/commands/ralph-run.md +138 -60
  29. package/Dev/i18n/fr/Laravel/commands/check-compliance.md +223 -115
  30. package/Dev/i18n/fr/React/commands/check-architecture.md +370 -53
  31. package/Dev/i18n/fr/React/commands/check-code-quality.md +454 -64
  32. package/Dev/i18n/fr/React/commands/check-testing.md +476 -102
  33. package/Dev/i18n/fr/Symfony/commands/check-compliance.md +188 -116
  34. package/Dev/i18n/fr/VueJS/commands/check-compliance.md +227 -102
  35. package/Dev/i18n/pt/Angular/commands/check-compliance.md +225 -175
  36. package/Dev/i18n/pt/Common/agents/ralph-conductor.md +211 -30
  37. package/Dev/i18n/pt/Common/commands/add-technology.md +149 -51
  38. package/Dev/i18n/pt/Common/commands/ralph-run.md +239 -35
  39. package/Dev/i18n/pt/Flutter/commands/analyze-performance.md +331 -46
  40. package/Dev/i18n/pt/Flutter/commands/check-compliance.md +234 -29
  41. package/Dev/i18n/pt/Flutter/commands/generate-feature.md +526 -51
  42. package/Dev/i18n/pt/Flutter/commands/generate-widget.md +515 -27
  43. package/Dev/i18n/pt/Flutter/commands/golden-update.md +322 -46
  44. package/Dev/i18n/pt/Flutter/commands/localization-check.md +278 -37
  45. package/Dev/i18n/pt/Laravel/commands/check-compliance.md +212 -104
  46. package/Dev/i18n/pt/React/commands/accessibility-check.md +151 -42
  47. package/Dev/i18n/pt/React/commands/bundle-analyze.md +300 -25
  48. package/Dev/i18n/pt/React/commands/check-architecture.md +369 -34
  49. package/Dev/i18n/pt/React/commands/check-code-quality.md +440 -34
  50. package/Dev/i18n/pt/React/commands/check-compliance.md +232 -62
  51. package/Dev/i18n/pt/React/commands/check-security.md +370 -31
  52. package/Dev/i18n/pt/React/commands/check-testing.md +473 -43
  53. package/Dev/i18n/pt/React/commands/generate-component.md +454 -19
  54. package/Dev/i18n/pt/React/commands/generate-hook.md +425 -24
  55. package/Dev/i18n/pt/React/commands/storybook-story.md +520 -35
  56. package/Dev/i18n/pt/ReactNative/commands/app-size.md +358 -387
  57. package/Dev/i18n/pt/ReactNative/commands/check-code-quality.md +246 -75
  58. package/Dev/i18n/pt/ReactNative/commands/check-compliance.md +191 -85
  59. package/Dev/i18n/pt/ReactNative/commands/check-security.md +363 -115
  60. package/Dev/i18n/pt/ReactNative/commands/check-testing.md +269 -79
  61. package/Dev/i18n/pt/ReactNative/commands/generate-screen.md +491 -324
  62. package/Dev/i18n/pt/ReactNative/commands/native-module.md +539 -82
  63. package/Dev/i18n/pt/ReactNative/commands/store-prepare.md +429 -185
  64. package/Dev/i18n/pt/ReactNative/rules/02-architecture.md +1084 -31
  65. package/Dev/i18n/pt/Symfony/commands/check-compliance.md +195 -123
  66. package/Dev/i18n/pt/UIUX/commands/a11y-audit.md +208 -24
  67. package/Dev/i18n/pt/UIUX/commands/a11y-component.md +281 -23
  68. package/Dev/i18n/pt/UIUX/commands/design-tokens.md +197 -33
  69. package/Dev/i18n/pt/UIUX/commands/user-flow.md +183 -20
  70. package/Dev/i18n/pt/VueJS/commands/check-compliance.md +228 -103
  71. package/Dev/i18n/pt/Workflow/commands/analyze.md +147 -146
  72. package/Dev/i18n/pt/Workflow/commands/design.md +205 -204
  73. package/Dev/i18n/pt/Workflow/commands/implement.md +184 -184
  74. package/Project/i18n/de/Sprint/commands/dev.md +339 -86
  75. package/Project/i18n/es/Sprint/commands/dev.md +342 -91
  76. package/Project/i18n/pt/Sprint/commands/dev.md +343 -92
  77. package/bundles/cursor/.cursorrules +1 -1
  78. package/bundles/windsurf/.windsurfrules +1 -1
  79. package/package.json +1 -1
@@ -1,143 +1,600 @@
1
1
  ---
2
- description: Comando: Criar Módulo Nativo
2
+ description: Guia de Criação de Módulo Nativo React Native
3
+ argument-hint: [arguments]
3
4
  ---
4
5
 
5
- # Comando: Criar Módulo Nativo
6
+ # Guia de Criação de Módulo Nativo React Native
6
7
 
7
- Guia para criar um módulo nativo (bridge) React Native para iOS e Android.
8
+ Você é um desenvolvedor React Native sênior. Você deve orientar a criação de um módulo nativo (bridge) para iOS e Android.
8
9
 
9
- ---
10
+ ## Argumentos
11
+ $ARGUMENTS
10
12
 
11
- ## Objetivo
13
+ Argumentos:
14
+ - Nome do módulo (ex.: `DeviceInfo`, `Biometrics`, `FileManager`)
15
+ - (Opcional) Funcionalidades: sync, async, events
12
16
 
13
- Este comando orienta a criação de um módulo nativo para acessar funcionalidades específicas da plataforma não disponíveis via JavaScript.
17
+ Exemplo: `/reactnative:native-module Biometrics async,events`
14
18
 
15
- ---
19
+ ## Modo de Planejamento
16
20
 
17
- ## Modo Plano
21
+ > O modo de planejamento é ativado automaticamente quando o escopo abrange múltiplos módulos ou requer investigação transversal.
18
22
 
19
- > O modo plano é ativado automaticamente quando o escopo abrange vários módulos ou requer investigação transversal.
23
+ ## MISSÃO
20
24
 
21
- ## Estrutura do Módulo
25
+ ### Etapa 1: Estrutura do Módulo
22
26
 
23
27
  ```
24
- src/native/{ModuleName}/
25
- ├── index.ts # API JavaScript
26
- ├── types.ts # Tipos TypeScript
27
- └── NativeModule.ts # Bridge
28
-
29
- android/app/src/main/java/com/{package}/{modulename}/
30
- ├── {ModuleName}Module.kt # Módulo principal Android
31
- └── {ModuleName}Package.kt # Registro do pacote
32
-
33
- ios/{AppName}/
34
- ├── {ModuleName}.swift # Módulo Swift
35
- └── {ModuleName}-Bridging-Header.h # Header Objective-C
28
+ src/
29
+ └── native/
30
+ └── {ModuleName}/
31
+ ├── index.ts # API JavaScript
32
+ ├── types.ts # Tipos TypeScript
33
+ └── NativeModule.ts # Bridge com TurboModule
34
+
35
+ android/
36
+ └── app/src/main/java/com/{package}/
37
+ └── {modulename}/
38
+ ├── {ModuleName}Module.kt # Módulo principal
39
+ └── {ModuleName}Package.kt # Registro do pacote
40
+
41
+ ios/
42
+ └── {AppName}/
43
+ ├── {ModuleName}.swift # Módulo Swift
44
+ └── {ModuleName}-Bridging-Header.h # Header para bridge Obj-C
36
45
  ```
37
46
 
38
- ---
39
-
40
- ## Implementação TypeScript
47
+ ### Etapa 2: API JavaScript/TypeScript
41
48
 
42
49
  ```typescript
43
- // types.ts
44
- export interface ModuleResult {
50
+ // src/native/{ModuleName}/types.ts
51
+ export interface {ModuleName}Result {
45
52
  success: boolean;
46
53
  data?: unknown;
47
54
  error?: string;
48
55
  }
49
56
 
50
- // NativeModule.ts
51
- import { NativeModules } from 'react-native';
57
+ export interface {ModuleName}Options {
58
+ timeout?: number;
59
+ // ...outras opções
60
+ }
52
61
 
53
- const { ModuleName } = NativeModules;
62
+ export type {ModuleName}EventType = 'onProgress' | 'onComplete' | 'onError';
54
63
 
55
- export const callNativeMethod = async (): Promise<ModuleResult> => {
56
- return await ModuleName.methodName();
57
- };
64
+ export interface {ModuleName}Event {
65
+ type: {ModuleName}EventType;
66
+ payload: unknown;
67
+ }
58
68
  ```
59
69
 
60
- ---
70
+ ```typescript
71
+ // src/native/{ModuleName}/NativeModule.ts
72
+ import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
73
+
74
+ const LINKING_ERROR =
75
+ `O pacote '{ModuleName}' não parece estar vinculado. Certifique-se de: \n\n` +
76
+ Platform.select({ ios: "- Você executou 'pod install'\n", default: '' }) +
77
+ '- Você reconstruiu o app após instalar o pacote\n' +
78
+ '- Você não está usando Expo Go\n';
79
+
80
+ // Tipo do módulo nativo
81
+ interface {ModuleName}NativeModule {
82
+ // Métodos síncronos
83
+ getConstant(): string;
84
+
85
+ // Métodos assíncronos
86
+ authenticate(options: {ModuleName}Options): Promise<{ModuleName}Result>;
87
+ isSupported(): Promise<boolean>;
88
+
89
+ // Para eventos
90
+ addListener(eventType: string): void;
91
+ removeListeners(count: number): void;
92
+ }
61
93
 
62
- ## Implementação Android (Kotlin)
94
+ const Native{ModuleName} = NativeModules.{ModuleName}
95
+ ? (NativeModules.{ModuleName} as {ModuleName}NativeModule)
96
+ : new Proxy(
97
+ {} as {ModuleName}NativeModule,
98
+ {
99
+ get() {
100
+ throw new Error(LINKING_ERROR);
101
+ },
102
+ }
103
+ );
104
+
105
+ export { Native{ModuleName} };
106
+ export const {ModuleName}EventEmitter = new NativeEventEmitter(
107
+ NativeModules.{ModuleName}
108
+ );
109
+ ```
110
+
111
+ ```typescript
112
+ // src/native/{ModuleName}/index.ts
113
+ import { useEffect, useCallback } from 'react';
114
+ import { Native{ModuleName}, {ModuleName}EventEmitter } from './NativeModule';
115
+ import type {
116
+ {ModuleName}Result,
117
+ {ModuleName}Options,
118
+ {ModuleName}Event,
119
+ } from './types';
120
+
121
+ /**
122
+ * Verifica se o recurso é suportado no dispositivo.
123
+ */
124
+ export async function isSupported(): Promise<boolean> {
125
+ try {
126
+ return await Native{ModuleName}.isSupported();
127
+ } catch {
128
+ return false;
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Inicia a autenticação biométrica.
134
+ */
135
+ export async function authenticate(
136
+ options: {ModuleName}Options = {}
137
+ ): Promise<{ModuleName}Result> {
138
+ return Native{ModuleName}.authenticate(options);
139
+ }
140
+
141
+ /**
142
+ * Hook para escutar eventos do módulo.
143
+ */
144
+ export function use{ModuleName}Events(
145
+ onEvent: (event: {ModuleName}Event) => void
146
+ ) {
147
+ useEffect(() => {
148
+ const subscription = {ModuleName}EventEmitter.addListener(
149
+ '{moduleName}Event',
150
+ onEvent
151
+ );
152
+
153
+ return () => {
154
+ subscription.remove();
155
+ };
156
+ }, [onEvent]);
157
+ }
158
+
159
+ /**
160
+ * Hook completo para usar o módulo.
161
+ */
162
+ export function use{ModuleName}() {
163
+ const [isAvailable, setIsAvailable] = useState<boolean | null>(null);
164
+ const [isAuthenticating, setIsAuthenticating] = useState(false);
165
+ const [error, setError] = useState<string | null>(null);
166
+
167
+ useEffect(() => {
168
+ isSupported().then(setIsAvailable);
169
+ }, []);
170
+
171
+ const authenticate = useCallback(async (options?: {ModuleName}Options) => {
172
+ if (!isAvailable) {
173
+ setError('{ModuleName} não disponível');
174
+ return { success: false, error: '{ModuleName} não disponível' };
175
+ }
176
+
177
+ setIsAuthenticating(true);
178
+ setError(null);
179
+
180
+ try {
181
+ const result = await Native{ModuleName}.authenticate(options || {});
182
+ return result;
183
+ } catch (err) {
184
+ const errorMessage = err instanceof Error ? err.message : 'Erro desconhecido';
185
+ setError(errorMessage);
186
+ return { success: false, error: errorMessage };
187
+ } finally {
188
+ setIsAuthenticating(false);
189
+ }
190
+ }, [isAvailable]);
191
+
192
+ return {
193
+ isAvailable,
194
+ isAuthenticating,
195
+ error,
196
+ authenticate,
197
+ };
198
+ }
199
+
200
+ // Exportar tudo
201
+ export * from './types';
202
+ ```
203
+
204
+ ### Etapa 3: Módulo Android (Kotlin)
63
205
 
64
206
  ```kotlin
65
- package com.yourapp.modulename
207
+ // android/app/src/main/java/com/{package}/{modulename}/{ModuleName}Module.kt
208
+ package com.{package}.{modulename}
66
209
 
67
210
  import com.facebook.react.bridge.*
211
+ import com.facebook.react.modules.core.DeviceEventManagerModule
212
+ import kotlinx.coroutines.*
68
213
 
69
- class ModuleNameModule(reactContext: ReactApplicationContext) :
70
- ReactContextBaseJavaModule(reactContext) {
214
+ class {ModuleName}Module(reactContext: ReactApplicationContext) :
215
+ ReactContextBaseJavaModule(reactContext),
216
+ CoroutineScope by MainScope() {
71
217
 
72
- override fun getName() = "ModuleName"
218
+ companion object {
219
+ const val NAME = "{ModuleName}"
220
+ private const val EVENT_NAME = "{moduleName}Event"
221
+ }
73
222
 
223
+ override fun getName(): String = NAME
224
+
225
+ // Constantes expostas ao JS
226
+ override fun getConstants(): MutableMap<String, Any> {
227
+ return hashMapOf(
228
+ "SUPPORTED" to isBiometricSupported()
229
+ )
230
+ }
231
+
232
+ // Método síncrono
233
+ @ReactMethod(isBlockingSynchronousMethod = true)
234
+ fun getConstant(): String {
235
+ return "some_value"
236
+ }
237
+
238
+ // Método assíncrono com Promise
239
+ @ReactMethod
240
+ fun isSupported(promise: Promise) {
241
+ launch {
242
+ try {
243
+ val supported = isBiometricSupported()
244
+ promise.resolve(supported)
245
+ } catch (e: Exception) {
246
+ promise.reject("ERROR", e.message, e)
247
+ }
248
+ }
249
+ }
250
+
251
+ @ReactMethod
252
+ fun authenticate(options: ReadableMap, promise: Promise) {
253
+ val timeout = if (options.hasKey("timeout")) options.getInt("timeout") else 30000
254
+
255
+ launch {
256
+ try {
257
+ // Implementar lógica nativa aqui
258
+ val result = performAuthentication(timeout)
259
+
260
+ val response = Arguments.createMap().apply {
261
+ putBoolean("success", result.success)
262
+ result.data?.let { putString("data", it) }
263
+ result.error?.let { putString("error", it) }
264
+ }
265
+ promise.resolve(response)
266
+ } catch (e: Exception) {
267
+ promise.reject("AUTH_ERROR", e.message, e)
268
+ }
269
+ }
270
+ }
271
+
272
+ // Enviar eventos ao JS
273
+ private fun sendEvent(eventName: String, params: WritableMap?) {
274
+ reactApplicationContext
275
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
276
+ .emit(eventName, params)
277
+ }
278
+
279
+ private fun emitProgress(progress: Int) {
280
+ val params = Arguments.createMap().apply {
281
+ putString("type", "onProgress")
282
+ putInt("progress", progress)
283
+ }
284
+ sendEvent(EVENT_NAME, params)
285
+ }
286
+
287
+ // Necessário para eventos
74
288
  @ReactMethod
75
- fun methodName(promise: Promise) {
76
- try {
77
- // Implementação nativa
78
- val result = Arguments.createMap()
79
- result.putBoolean("success", true)
80
- promise.resolve(result)
81
- } catch (e: Exception) {
82
- promise.reject("ERROR_CODE", e.message, e)
289
+ fun addListener(eventName: String) {
290
+ // Necessário para NativeEventEmitter
291
+ }
292
+
293
+ @ReactMethod
294
+ fun removeListeners(count: Int) {
295
+ // Necessário para NativeEventEmitter
296
+ }
297
+
298
+ // Lógica de negócio nativa
299
+ private suspend fun performAuthentication(timeout: Int): AuthResult {
300
+ return withContext(Dispatchers.IO) {
301
+ // Implementar aqui
302
+ AuthResult(success = true, data = "authenticated")
83
303
  }
84
304
  }
305
+
306
+ private fun isBiometricSupported(): Boolean {
307
+ // Implementar verificação
308
+ return true
309
+ }
310
+
311
+ override fun onCatalystInstanceDestroy() {
312
+ super.onCatalystInstanceDestroy()
313
+ cancel() // Cancelar coroutines
314
+ }
85
315
  }
316
+
317
+ data class AuthResult(
318
+ val success: Boolean,
319
+ val data: String? = null,
320
+ val error: String? = null
321
+ )
86
322
  ```
87
323
 
88
- ---
324
+ ```kotlin
325
+ // android/app/src/main/java/com/{package}/{modulename}/{ModuleName}Package.kt
326
+ package com.{package}.{modulename}
327
+
328
+ import com.facebook.react.ReactPackage
329
+ import com.facebook.react.bridge.NativeModule
330
+ import com.facebook.react.bridge.ReactApplicationContext
331
+ import com.facebook.react.uimanager.ViewManager
332
+
333
+ class {ModuleName}Package : ReactPackage {
334
+ override fun createNativeModules(
335
+ reactContext: ReactApplicationContext
336
+ ): List<NativeModule> {
337
+ return listOf({ModuleName}Module(reactContext))
338
+ }
339
+
340
+ override fun createViewManagers(
341
+ reactContext: ReactApplicationContext
342
+ ): List<ViewManager<*, *>> {
343
+ return emptyList()
344
+ }
345
+ }
346
+ ```
347
+
348
+ ```kotlin
349
+ // Adicionar ao MainApplication.kt
350
+ override fun getPackages(): List<ReactPackage> =
351
+ PackageList(this).packages.apply {
352
+ add({ModuleName}Package())
353
+ }
354
+ ```
89
355
 
90
- ## Implementação iOS (Swift)
356
+ ### Etapa 4: Módulo iOS (Swift)
91
357
 
92
358
  ```swift
93
- @objc(ModuleName)
94
- class ModuleName: NSObject {
359
+ // ios/{AppName}/{ModuleName}.swift
360
+ import Foundation
361
+ import React
362
+ import LocalAuthentication // ou outro framework necessário
363
+
364
+ @objc({ModuleName})
365
+ class {ModuleName}: RCTEventEmitter {
366
+
367
+ private let eventName = "{moduleName}Event"
368
+
369
+ // MARK: - Configuração do Módulo
370
+
371
+ @objc override static func moduleName() -> String! {
372
+ return "{ModuleName}"
373
+ }
374
+
375
+ @objc override static func requiresMainQueueSetup() -> Bool {
376
+ return false
377
+ }
378
+
379
+ // Eventos suportados
380
+ override func supportedEvents() -> [String]! {
381
+ return [eventName]
382
+ }
383
+
384
+ // Constantes expostas ao JS
385
+ @objc override func constantsToExport() -> [AnyHashable : Any]! {
386
+ return [
387
+ "SUPPORTED": isBiometricSupported()
388
+ ]
389
+ }
390
+
391
+ // MARK: - Métodos
95
392
 
96
393
  @objc
97
- func methodName(
98
- _ resolve: @escaping RCTPromiseResolveBlock,
394
+ func getConstant() -> String {
395
+ return "some_value"
396
+ }
397
+
398
+ @objc(isSupported:rejecter:)
399
+ func isSupported(
400
+ resolver resolve: @escaping RCTPromiseResolveBlock,
99
401
  rejecter reject: @escaping RCTPromiseRejectBlock
100
402
  ) {
101
- do {
102
- // Implementação nativa
103
- let result: [String: Any] = ["success": true]
104
- resolve(result)
105
- } catch {
106
- reject("ERROR_CODE", error.localizedDescription, error)
403
+ resolve(isBiometricSupported())
404
+ }
405
+
406
+ @objc(authenticate:resolver:rejecter:)
407
+ func authenticate(
408
+ options: NSDictionary,
409
+ resolver resolve: @escaping RCTPromiseResolveBlock,
410
+ rejecter reject: @escaping RCTPromiseRejectBlock
411
+ ) {
412
+ let timeout = options["timeout"] as? Int ?? 30000
413
+
414
+ DispatchQueue.global(qos: .userInitiated).async { [weak self] in
415
+ self?.performAuthentication(timeout: timeout) { result in
416
+ switch result {
417
+ case .success(let data):
418
+ resolve([
419
+ "success": true,
420
+ "data": data
421
+ ])
422
+ case .failure(let error):
423
+ resolve([
424
+ "success": false,
425
+ "error": error.localizedDescription
426
+ ])
427
+ }
428
+ }
107
429
  }
108
430
  }
109
431
 
110
- @objc
111
- static func requiresMainQueueSetup() -> Bool {
112
- return false
432
+ // MARK: - Métodos Privados
433
+
434
+ private func isBiometricSupported() -> Bool {
435
+ let context = LAContext()
436
+ var error: NSError?
437
+ return context.canEvaluatePolicy(
438
+ .deviceOwnerAuthenticationWithBiometrics,
439
+ error: &error
440
+ )
441
+ }
442
+
443
+ private func performAuthentication(
444
+ timeout: Int,
445
+ completion: @escaping (Result<String, Error>) -> Void
446
+ ) {
447
+ let context = LAContext()
448
+ context.localizedFallbackTitle = "Usar senha"
449
+
450
+ context.evaluatePolicy(
451
+ .deviceOwnerAuthenticationWithBiometrics,
452
+ localizedReason: "Autenticação necessária"
453
+ ) { success, error in
454
+ if success {
455
+ completion(.success("authenticated"))
456
+ } else if let error = error {
457
+ completion(.failure(error))
458
+ }
459
+ }
460
+ }
461
+
462
+ // Emitir evento ao JS
463
+ private func emitProgress(_ progress: Int) {
464
+ sendEvent(withName: eventName, body: [
465
+ "type": "onProgress",
466
+ "progress": progress
467
+ ])
113
468
  }
114
469
  }
115
470
  ```
116
471
 
117
- ---
472
+ ```objc
473
+ // ios/{AppName}/{ModuleName}-Bridging-Header.h
474
+ #import <React/RCTBridgeModule.h>
475
+ #import <React/RCTEventEmitter.h>
118
476
 
119
- ## Casos de Uso Comuns
477
+ // Expor métodos ao Objective-C
478
+ @interface RCT_EXTERN_MODULE({ModuleName}, RCTEventEmitter)
120
479
 
121
- - Biometria (Face ID, Touch ID, Fingerprint)
122
- - Gerenciamento de arquivos nativos
123
- - Acesso a hardware específico
124
- - Funcionalidades de segurança avançadas
125
- - Integração com SDKs nativos
126
- - Otimizações de performance críticas
480
+ RCT_EXTERN_METHOD(isSupported:(RCTPromiseResolveBlock)resolve
481
+ rejecter:(RCTPromiseRejectBlock)reject)
127
482
 
128
- ---
483
+ RCT_EXTERN_METHOD(authenticate:(NSDictionary *)options
484
+ resolver:(RCTPromiseResolveBlock)resolve
485
+ rejecter:(RCTPromiseRejectBlock)reject)
129
486
 
130
- ## Checklist
487
+ RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(getConstant)
131
488
 
132
- - [ ] Estrutura de módulo criada
133
- - [ ] Implementação Android completa
134
- - [ ] Implementação iOS completa
135
- - [ ] Tipagem TypeScript definida
136
- - [ ] Testes unitários criados
137
- - [ ] Documentação escrita
138
- - [ ] Tratamento de erros implementado
139
- - [ ] Testado em ambas plataformas
489
+ @end
490
+ ```
140
491
 
141
- ---
492
+ ### Etapa 5: Testes do Módulo
142
493
 
143
- **Módulos nativos são poderosos mas aumentam complexidade. Use apenas quando necessário.**
494
+ ```typescript
495
+ // src/native/{ModuleName}/__tests__/{ModuleName}.test.ts
496
+ import { NativeModules } from 'react-native';
497
+ import { authenticate, isSupported } from '../index';
498
+
499
+ // Mock do módulo nativo
500
+ jest.mock('react-native', () => ({
501
+ NativeModules: {
502
+ {ModuleName}: {
503
+ isSupported: jest.fn(),
504
+ authenticate: jest.fn(),
505
+ },
506
+ },
507
+ NativeEventEmitter: jest.fn(() => ({
508
+ addListener: jest.fn(() => ({ remove: jest.fn() })),
509
+ })),
510
+ Platform: {
511
+ OS: 'ios',
512
+ select: jest.fn((obj) => obj.ios),
513
+ },
514
+ }));
515
+
516
+ describe('{ModuleName}', () => {
517
+ beforeEach(() => {
518
+ jest.clearAllMocks();
519
+ });
520
+
521
+ describe('isSupported', () => {
522
+ it('retorna true quando suportado', async () => {
523
+ (NativeModules.{ModuleName}.isSupported as jest.Mock).mockResolvedValue(true);
524
+
525
+ const result = await isSupported();
526
+
527
+ expect(result).toBe(true);
528
+ });
529
+
530
+ it('retorna false em caso de erro', async () => {
531
+ (NativeModules.{ModuleName}.isSupported as jest.Mock).mockRejectedValue(
532
+ new Error('Não disponível')
533
+ );
534
+
535
+ const result = await isSupported();
536
+
537
+ expect(result).toBe(false);
538
+ });
539
+ });
540
+
541
+ describe('authenticate', () => {
542
+ it('retorna resultado de sucesso', async () => {
543
+ const mockResult = { success: true, data: 'authenticated' };
544
+ (NativeModules.{ModuleName}.authenticate as jest.Mock).mockResolvedValue(mockResult);
545
+
546
+ const result = await authenticate({ timeout: 5000 });
547
+
548
+ expect(result).toEqual(mockResult);
549
+ expect(NativeModules.{ModuleName}.authenticate).toHaveBeenCalledWith({
550
+ timeout: 5000,
551
+ });
552
+ });
553
+
554
+ it('trata falha de autenticação', async () => {
555
+ const mockResult = { success: false, error: 'Usuário cancelou' };
556
+ (NativeModules.{ModuleName}.authenticate as jest.Mock).mockResolvedValue(mockResult);
557
+
558
+ const result = await authenticate();
559
+
560
+ expect(result.success).toBe(false);
561
+ expect(result.error).toBe('Usuário cancelou');
562
+ });
563
+ });
564
+ });
565
+ ```
566
+
567
+ ### Resumo
568
+
569
+ ```
570
+ ══════════════════════════════════════════════════════════════
571
+ ✅ MÓDULO NATIVO - {ModuleName}
572
+ ══════════════════════════════════════════════════════════════
573
+
574
+ 📁 Arquivos criados:
575
+
576
+ JavaScript/TypeScript:
577
+ - src/native/{ModuleName}/index.ts
578
+ - src/native/{ModuleName}/types.ts
579
+ - src/native/{ModuleName}/NativeModule.ts
580
+
581
+ Android (Kotlin):
582
+ - android/.../{ ModuleName}Module.kt
583
+ - android/.../{ ModuleName}Package.kt
584
+
585
+ iOS (Swift):
586
+ - ios/{AppName}/{ModuleName}.swift
587
+ - ios/{AppName}/{ModuleName}-Bridging-Header.h
588
+
589
+ 📝 API exposta:
590
+ - isSupported(): Promise<boolean>
591
+ - authenticate(options): Promise<Result>
592
+ - use{ModuleName}(): Hook completo
593
+ - use{ModuleName}Events(): Listener de eventos
594
+
595
+ 🔧 Próximos passos:
596
+ 1. Android: Adicionar {ModuleName}Package ao MainApplication.kt
597
+ 2. iOS: pod install
598
+ 3. Reconstruir ambos os apps
599
+ 4. Testar em dispositivo físico
600
+ ```