@yakuzaa/jade-runtime 0.1.0

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 (113) hide show
  1. package/dist/apis/audit_service.d.ts +43 -0
  2. package/dist/apis/audit_service.d.ts.map +1 -0
  3. package/dist/apis/audit_service.js +73 -0
  4. package/dist/apis/audit_service.js.map +1 -0
  5. package/dist/apis/auth_service.d.ts +51 -0
  6. package/dist/apis/auth_service.d.ts.map +1 -0
  7. package/dist/apis/auth_service.js +120 -0
  8. package/dist/apis/auth_service.js.map +1 -0
  9. package/dist/apis/console_api.d.ts +34 -0
  10. package/dist/apis/console_api.d.ts.map +1 -0
  11. package/dist/apis/console_api.js +90 -0
  12. package/dist/apis/console_api.js.map +1 -0
  13. package/dist/apis/datetime_api.d.ts +13 -0
  14. package/dist/apis/datetime_api.d.ts.map +1 -0
  15. package/dist/apis/datetime_api.js +89 -0
  16. package/dist/apis/datetime_api.js.map +1 -0
  17. package/dist/apis/http_client.d.ts +32 -0
  18. package/dist/apis/http_client.d.ts.map +1 -0
  19. package/dist/apis/http_client.js +83 -0
  20. package/dist/apis/http_client.js.map +1 -0
  21. package/dist/apis/permission_service.d.ts +18 -0
  22. package/dist/apis/permission_service.d.ts.map +1 -0
  23. package/dist/apis/permission_service.js +56 -0
  24. package/dist/apis/permission_service.js.map +1 -0
  25. package/dist/core/event_loop.d.ts +14 -0
  26. package/dist/core/event_loop.d.ts.map +1 -0
  27. package/dist/core/event_loop.js +60 -0
  28. package/dist/core/event_loop.js.map +1 -0
  29. package/dist/core/memory_manager.d.ts +43 -0
  30. package/dist/core/memory_manager.d.ts.map +1 -0
  31. package/dist/core/memory_manager.js +218 -0
  32. package/dist/core/memory_manager.js.map +1 -0
  33. package/dist/core/runtime.d.ts +18 -0
  34. package/dist/core/runtime.d.ts.map +1 -0
  35. package/dist/core/runtime.js +116 -0
  36. package/dist/core/runtime.js.map +1 -0
  37. package/dist/persistence/local_datastore.d.ts +34 -0
  38. package/dist/persistence/local_datastore.d.ts.map +1 -0
  39. package/dist/persistence/local_datastore.js +112 -0
  40. package/dist/persistence/local_datastore.js.map +1 -0
  41. package/dist/persistence/sync_manager.d.ts +49 -0
  42. package/dist/persistence/sync_manager.d.ts.map +1 -0
  43. package/dist/persistence/sync_manager.js +187 -0
  44. package/dist/persistence/sync_manager.js.map +1 -0
  45. package/dist/pwa/pwa_generator.d.ts +16 -0
  46. package/dist/pwa/pwa_generator.d.ts.map +1 -0
  47. package/dist/pwa/pwa_generator.js +107 -0
  48. package/dist/pwa/pwa_generator.js.map +1 -0
  49. package/dist/stdlib/matematica.d.ts +121 -0
  50. package/dist/stdlib/matematica.d.ts.map +1 -0
  51. package/dist/stdlib/matematica.js +250 -0
  52. package/dist/stdlib/matematica.js.map +1 -0
  53. package/dist/stdlib/moeda.d.ts +129 -0
  54. package/dist/stdlib/moeda.d.ts.map +1 -0
  55. package/dist/stdlib/moeda.js +212 -0
  56. package/dist/stdlib/moeda.js.map +1 -0
  57. package/dist/stdlib/texto.d.ts +101 -0
  58. package/dist/stdlib/texto.d.ts.map +1 -0
  59. package/dist/stdlib/texto.js +205 -0
  60. package/dist/stdlib/texto.js.map +1 -0
  61. package/dist/stdlib/xml.d.ts +77 -0
  62. package/dist/stdlib/xml.d.ts.map +1 -0
  63. package/dist/stdlib/xml.js +212 -0
  64. package/dist/stdlib/xml.js.map +1 -0
  65. package/dist/ui/binding.d.ts +22 -0
  66. package/dist/ui/binding.d.ts.map +1 -0
  67. package/dist/ui/binding.js +62 -0
  68. package/dist/ui/binding.js.map +1 -0
  69. package/dist/ui/components/botao.d.ts +4 -0
  70. package/dist/ui/components/botao.d.ts.map +1 -0
  71. package/dist/ui/components/botao.js +4 -0
  72. package/dist/ui/components/botao.js.map +1 -0
  73. package/dist/ui/components/campo.d.ts +8 -0
  74. package/dist/ui/components/campo.d.ts.map +1 -0
  75. package/dist/ui/components/campo.js +9 -0
  76. package/dist/ui/components/campo.js.map +1 -0
  77. package/dist/ui/components/card.d.ts +4 -0
  78. package/dist/ui/components/card.d.ts.map +1 -0
  79. package/dist/ui/components/card.js +4 -0
  80. package/dist/ui/components/card.js.map +1 -0
  81. package/dist/ui/components/formulario.d.ts +4 -0
  82. package/dist/ui/components/formulario.d.ts.map +1 -0
  83. package/dist/ui/components/formulario.js +4 -0
  84. package/dist/ui/components/formulario.js.map +1 -0
  85. package/dist/ui/components/tabela.d.ts +3 -0
  86. package/dist/ui/components/tabela.d.ts.map +1 -0
  87. package/dist/ui/components/tabela.js +4 -0
  88. package/dist/ui/components/tabela.js.map +1 -0
  89. package/dist/ui/reactive.d.ts +61 -0
  90. package/dist/ui/reactive.d.ts.map +1 -0
  91. package/dist/ui/reactive.js +149 -0
  92. package/dist/ui/reactive.js.map +1 -0
  93. package/dist/ui/refs.d.ts +13 -0
  94. package/dist/ui/refs.d.ts.map +1 -0
  95. package/dist/ui/refs.js +32 -0
  96. package/dist/ui/refs.js.map +1 -0
  97. package/dist/ui/router.d.ts +39 -0
  98. package/dist/ui/router.d.ts.map +1 -0
  99. package/dist/ui/router.js +74 -0
  100. package/dist/ui/router.js.map +1 -0
  101. package/dist/ui/theme.d.ts +19 -0
  102. package/dist/ui/theme.d.ts.map +1 -0
  103. package/dist/ui/theme.js +183 -0
  104. package/dist/ui/theme.js.map +1 -0
  105. package/dist/ui/ui_engine.d.ts +89 -0
  106. package/dist/ui/ui_engine.d.ts.map +1 -0
  107. package/dist/ui/ui_engine.js +406 -0
  108. package/dist/ui/ui_engine.js.map +1 -0
  109. package/dist/ui/virtual_list.d.ts +29 -0
  110. package/dist/ui/virtual_list.d.ts.map +1 -0
  111. package/dist/ui/virtual_list.js +88 -0
  112. package/dist/ui/virtual_list.js.map +1 -0
  113. package/package.json +76 -0
@@ -0,0 +1,116 @@
1
+ import { MemoryManager } from './memory_manager';
2
+ import { EventLoop } from './event_loop';
3
+ export class JadeRuntime {
4
+ memory;
5
+ events;
6
+ wasmInstance = null;
7
+ exports = {};
8
+ debug;
9
+ constructor(config = {}) {
10
+ this.memory = new MemoryManager();
11
+ this.events = new EventLoop();
12
+ this.debug = config.debug ?? false;
13
+ }
14
+ // Carrega e instancia um módulo WASM.
15
+ // Aceita: BufferSource (Uint8Array), Response (streaming), ou WebAssembly.Module
16
+ async load(wasmSource) {
17
+ const imports = this.buildImports();
18
+ let instance;
19
+ if (wasmSource instanceof WebAssembly.Module) {
20
+ // Já é um módulo compilado — instanciar diretamente
21
+ // WebAssembly.instantiate(Module) retorna Instance diretamente (não { instance })
22
+ instance = await WebAssembly.instantiate(wasmSource, imports);
23
+ }
24
+ else if (wasmSource instanceof Response) {
25
+ const result = await WebAssembly.instantiateStreaming(wasmSource, imports);
26
+ instance = result.instance;
27
+ }
28
+ else {
29
+ // BufferSource (Uint8Array, ArrayBuffer)
30
+ // WebAssembly.instantiate(Buffer) retorna { module, instance }
31
+ const result = await WebAssembly.instantiate(wasmSource, imports);
32
+ instance = result.instance;
33
+ }
34
+ this.wasmInstance = instance;
35
+ this.exports = instance.exports;
36
+ // Conectar a memória exportada pelo WASM ao MemoryManager
37
+ // O WASM exporta "memory" — é esse buffer que devemos ler/escrever
38
+ if (instance.exports.memory instanceof WebAssembly.Memory) {
39
+ this.memory.connectWasmMemory(instance.exports.memory);
40
+ }
41
+ if (this.debug) {
42
+ console.log('[JADE Runtime] Módulo carregado. Exports:', Object.keys(this.exports));
43
+ }
44
+ }
45
+ // Chama uma função exportada pelo WASM
46
+ call(funcName, ...args) {
47
+ if (!this.exports[funcName]) {
48
+ throw new Error(`Função '${funcName}' não encontrada no módulo WASM`);
49
+ }
50
+ return this.exports[funcName](...args);
51
+ }
52
+ // Registra handler para evento JADE
53
+ on(event, handler) {
54
+ this.events.on(event, handler);
55
+ }
56
+ // Acesso ao gerenciador de memória (para testes e integração)
57
+ getMemory() {
58
+ return this.memory;
59
+ }
60
+ // Constrói o objeto de imports que o WASM recebe
61
+ buildImports() {
62
+ return {
63
+ jade: {
64
+ log_i32: (value) => {
65
+ if (this.debug)
66
+ console.log('[JADE]', value);
67
+ },
68
+ log_f64: (value) => {
69
+ if (this.debug)
70
+ console.log('[JADE]', value);
71
+ },
72
+ log_str: (ptr) => {
73
+ const str = this.memory.readString(ptr);
74
+ if (this.debug)
75
+ console.log('[JADE]', str);
76
+ },
77
+ malloc: (size) => {
78
+ return this.memory.malloc(size);
79
+ },
80
+ free: (ptr) => {
81
+ this.memory.free(ptr);
82
+ },
83
+ erro: (msgPtr) => {
84
+ const msg = this.memory.readString(msgPtr);
85
+ throw new Error(`[JADE Erro] ${msg}`);
86
+ },
87
+ emitir_evento: (nomePtr, dadosPtr) => {
88
+ const nome = this.memory.readString(nomePtr);
89
+ this.events.emit(nome, dadosPtr);
90
+ if (this.debug)
91
+ console.log(`[JADE Evento] ${nome}`);
92
+ },
93
+ lista_tamanho: (listaPtr) => {
94
+ const view = new DataView(this.memory.getMemory().buffer);
95
+ return view.getInt32(listaPtr, true);
96
+ },
97
+ lista_obter: (listaPtr, index) => {
98
+ const view = new DataView(this.memory.getMemory().buffer);
99
+ return view.getInt32(listaPtr + 4 + index * 4, true);
100
+ },
101
+ concat: (ptrA, ptrB) => {
102
+ const strA = this.memory.readString(ptrA);
103
+ const strB = this.memory.readString(ptrB);
104
+ const result = strA + strB;
105
+ const encoded = new TextEncoder().encode(result);
106
+ const ptr = this.memory.malloc(encoded.length + 1);
107
+ const bytes = new Uint8Array(this.memory.getMemory().buffer, ptr, encoded.length + 1);
108
+ bytes.set(encoded);
109
+ bytes[encoded.length] = 0;
110
+ return ptr;
111
+ },
112
+ }
113
+ };
114
+ }
115
+ }
116
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../core/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAMzC,MAAM,OAAO,WAAW;IACd,MAAM,CAAgB;IACtB,MAAM,CAAY;IAClB,YAAY,GAAgC,IAAI,CAAC;IACjD,OAAO,GAAQ,EAAE,CAAC;IAClB,KAAK,CAAU;IAEvB,YAAY,SAA4B,EAAE;QACxC,IAAI,CAAC,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC;IACrC,CAAC;IAED,sCAAsC;IACtC,iFAAiF;IACjF,KAAK,CAAC,IAAI,CAAC,UAAwD;QACjE,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAEpC,IAAI,QAA8B,CAAC;QAEnC,IAAI,UAAU,YAAY,WAAW,CAAC,MAAM,EAAE,CAAC;YAC7C,oDAAoD;YACpD,kFAAkF;YAClF,QAAQ,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAChE,CAAC;aAAM,IAAI,UAAU,YAAY,QAAQ,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC3E,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,yCAAyC;YACzC,+DAA+D;YAC/D,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAClE,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC7B,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QAEhC,0DAA0D;QAC1D,mEAAmE;QACnE,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,YAAY,WAAW,CAAC,MAAM,EAAE,CAAC;YAC1D,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzD,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,2CAA2C,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC,QAAgB,EAAE,GAAG,IAAW;QACnC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,WAAW,QAAQ,iCAAiC,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,oCAAoC;IACpC,EAAE,CAAC,KAAa,EAAE,OAAiC;QACjD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,8DAA8D;IAC9D,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,iDAAiD;IACzC,YAAY;QAClB,OAAO;YACL,IAAI,EAAE;gBACJ,OAAO,EAAE,CAAC,KAAa,EAAE,EAAE;oBACzB,IAAI,IAAI,CAAC,KAAK;wBAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAC/C,CAAC;gBACD,OAAO,EAAE,CAAC,KAAa,EAAE,EAAE;oBACzB,IAAI,IAAI,CAAC,KAAK;wBAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAC/C,CAAC;gBACD,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE;oBACvB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;oBACxC,IAAI,IAAI,CAAC,KAAK;wBAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;gBAC7C,CAAC;gBACD,MAAM,EAAE,CAAC,IAAY,EAAU,EAAE;oBAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAClC,CAAC;gBACD,IAAI,EAAE,CAAC,GAAW,EAAQ,EAAE;oBAC1B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACxB,CAAC;gBACD,IAAI,EAAE,CAAC,MAAc,EAAQ,EAAE;oBAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;oBAC3C,MAAM,IAAI,KAAK,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC;gBACxC,CAAC;gBACD,aAAa,EAAE,CAAC,OAAe,EAAE,QAAgB,EAAQ,EAAE;oBACzD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;oBAC7C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;oBACjC,IAAI,IAAI,CAAC,KAAK;wBAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;gBACvD,CAAC;gBACD,aAAa,EAAE,CAAC,QAAgB,EAAU,EAAE;oBAC1C,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC;oBAC1D,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBACvC,CAAC;gBACD,WAAW,EAAE,CAAC,QAAgB,EAAE,KAAa,EAAU,EAAE;oBACvD,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC;oBAC1D,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;gBACvD,CAAC;gBACD,MAAM,EAAE,CAAC,IAAY,EAAE,IAAY,EAAU,EAAE;oBAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;oBAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;oBAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;oBAC3B,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBACjD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBACnD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBACtF,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBACnB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAC1B,OAAO,GAAG,CAAC;gBACb,CAAC;aACF;SACF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,34 @@
1
+ export interface Query {
2
+ where?: Record<string, any>;
3
+ orderBy?: {
4
+ field: string;
5
+ direction: 'asc' | 'desc';
6
+ };
7
+ limit?: number;
8
+ }
9
+ export interface FieldDelta {
10
+ de: any;
11
+ para: any;
12
+ }
13
+ export interface UpdateResult {
14
+ record: any;
15
+ baseRev: string;
16
+ deltas: Record<string, FieldDelta>;
17
+ }
18
+ export declare class LocalDatastore {
19
+ private db;
20
+ private dbName;
21
+ private tables;
22
+ constructor(dbName: string, tables: string[]);
23
+ init(): Promise<void>;
24
+ insert(table: string, record: any): Promise<any>;
25
+ find(table: string, query?: Query): Promise<any[]>;
26
+ findById(table: string, id: string): Promise<any | null>;
27
+ update(table: string, id: string, changes: any): Promise<UpdateResult>;
28
+ delete(table: string, id: string): Promise<void>;
29
+ private runTransaction;
30
+ private generateUUID;
31
+ private generateRev;
32
+ private bumpRev;
33
+ }
34
+ //# sourceMappingURL=local_datastore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local_datastore.d.ts","sourceRoot":"","sources":["../../persistence/local_datastore.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,KAAK;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,CAAC;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,GAAG,CAAC;IACR,IAAI,EAAE,GAAG,CAAC;CACX;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,GAAG,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,EAAE,CAA4B;IACtC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAW;gBAEb,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IAKtC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBrB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAWhD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IA6BlD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAUxD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC;IAuBtE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,OAAO;CAKhB"}
@@ -0,0 +1,112 @@
1
+ export class LocalDatastore {
2
+ db = null;
3
+ dbName;
4
+ tables;
5
+ constructor(dbName, tables) {
6
+ this.dbName = dbName;
7
+ this.tables = tables;
8
+ }
9
+ async init() {
10
+ return new Promise((resolve, reject) => {
11
+ const request = indexedDB.open(this.dbName, 1);
12
+ request.onupgradeneeded = (event) => {
13
+ const db = event.target.result;
14
+ for (const table of this.tables) {
15
+ if (!db.objectStoreNames.contains(table)) {
16
+ db.createObjectStore(table, { keyPath: 'id' });
17
+ }
18
+ }
19
+ };
20
+ request.onsuccess = () => {
21
+ this.db = request.result;
22
+ resolve();
23
+ };
24
+ request.onerror = () => reject(request.error);
25
+ });
26
+ }
27
+ async insert(table, record) {
28
+ if (!record.id) {
29
+ record.id = this.generateUUID();
30
+ }
31
+ // Todo registro nasce com _rev '1-xxxx'
32
+ if (!record._rev) {
33
+ record._rev = this.generateRev(0);
34
+ }
35
+ return this.runTransaction(table, 'readwrite', store => store.add(record));
36
+ }
37
+ async find(table, query) {
38
+ const all = await this.runTransaction(table, 'readonly', store => store.getAll());
39
+ let results = all;
40
+ if (query?.where) {
41
+ results = results.filter(record => Object.entries(query.where).every(([key, val]) => record[key] === val));
42
+ }
43
+ if (query?.orderBy) {
44
+ const { field, direction } = query.orderBy;
45
+ results.sort((a, b) => {
46
+ const cmp = a[field] < b[field] ? -1 : a[field] > b[field] ? 1 : 0;
47
+ return direction === 'asc' ? cmp : -cmp;
48
+ });
49
+ }
50
+ if (query?.limit) {
51
+ results = results.slice(0, query.limit);
52
+ }
53
+ return results;
54
+ }
55
+ async findById(table, id) {
56
+ const result = await this.runTransaction(table, 'readonly', store => store.get(id));
57
+ return result ?? null;
58
+ }
59
+ // Retorna o registro atualizado, o _rev anterior (baseRev) e os
60
+ // deltas por campo — necessários para o SyncManager detectar conflitos.
61
+ async update(table, id, changes) {
62
+ const record = await this.findById(table, id);
63
+ if (!record)
64
+ throw new Error(`Registro '${id}' não encontrado em '${table}'`);
65
+ // Captura o _rev atual antes de qualquer alteração
66
+ const baseRev = record._rev ?? this.generateRev(0);
67
+ // Monta deltas campo a campo (ignora campos sem mudança)
68
+ const deltas = {};
69
+ for (const [campo, novoValor] of Object.entries(changes)) {
70
+ if (campo !== '_rev' && record[campo] !== novoValor) {
71
+ deltas[campo] = { de: record[campo], para: novoValor };
72
+ }
73
+ }
74
+ // Gera novo _rev com sequência incrementada
75
+ const newRev = this.bumpRev(baseRev);
76
+ const updated = { ...record, ...changes, _rev: newRev };
77
+ await this.runTransaction(table, 'readwrite', store => store.put(updated));
78
+ return { record: updated, baseRev, deltas };
79
+ }
80
+ async delete(table, id) {
81
+ return this.runTransaction(table, 'readwrite', store => store.delete(id));
82
+ }
83
+ runTransaction(table, mode, operation) {
84
+ return new Promise((resolve, reject) => {
85
+ if (!this.db)
86
+ throw new Error('Datastore não inicializado');
87
+ const tx = this.db.transaction(table, mode);
88
+ const store = tx.objectStore(table);
89
+ const request = operation(store);
90
+ request.onsuccess = () => resolve(request.result);
91
+ request.onerror = () => reject(request.error);
92
+ });
93
+ }
94
+ generateUUID() {
95
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
96
+ const r = Math.random() * 16 | 0;
97
+ return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
98
+ });
99
+ }
100
+ // Gera _rev inicial: '1-xxxxxxx'
101
+ generateRev(seq) {
102
+ const hash = Math.random().toString(36).slice(2, 9);
103
+ return `${seq + 1}-${hash}`;
104
+ }
105
+ // Incrementa a sequência do _rev: '2-xxxxxxx' → '3-xxxxxxx'
106
+ bumpRev(rev) {
107
+ const seq = parseInt(rev.split('-')[0] ?? '0', 10);
108
+ const hash = Math.random().toString(36).slice(2, 9);
109
+ return `${seq + 1}-${hash}`;
110
+ }
111
+ }
112
+ //# sourceMappingURL=local_datastore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local_datastore.js","sourceRoot":"","sources":["../../persistence/local_datastore.ts"],"names":[],"mappings":"AAkBA,MAAM,OAAO,cAAc;IACjB,EAAE,GAAuB,IAAI,CAAC;IAC9B,MAAM,CAAS;IACf,MAAM,CAAW;IAEzB,YAAY,MAAc,EAAE,MAAgB;QAC1C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAE/C,OAAO,CAAC,eAAe,GAAG,CAAC,KAAK,EAAE,EAAE;gBAClC,MAAM,EAAE,GAAI,KAAK,CAAC,MAA2B,CAAC,MAAM,CAAC;gBACrD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAChC,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;wBACzC,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;oBACjD,CAAC;gBACH,CAAC;YACH,CAAC,CAAC;YAEF,OAAO,CAAC,SAAS,GAAG,GAAG,EAAE;gBACvB,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;gBACzB,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;YAEF,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,MAAW;QACrC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAClC,CAAC;QACD,wCAAwC;QACxC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,KAAa;QACrC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CACnC,KAAK,EAAE,UAAU,EACjB,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CACxB,CAAC;QAEF,IAAI,OAAO,GAAG,GAAG,CAAC;QAElB,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;YACjB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAChC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CACxE,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,EAAE,OAAO,EAAE,CAAC;YACnB,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACpB,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnE,OAAO,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC1C,CAAC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;YACjB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,EAAU;QACtC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CACtC,KAAK,EAAE,UAAU,EACjB,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CACvB,CAAC;QACF,OAAO,MAAM,IAAI,IAAI,CAAC;IACxB,CAAC;IAED,gEAAgE;IAChE,wEAAwE;IACxE,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,EAAU,EAAE,OAAY;QAClD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,aAAa,EAAE,wBAAwB,KAAK,GAAG,CAAC,CAAC;QAE9E,mDAAmD;QACnD,MAAM,OAAO,GAAW,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAE3D,yDAAyD;QACzD,MAAM,MAAM,GAA+B,EAAE,CAAC;QAC9C,KAAK,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACzD,IAAI,KAAK,KAAK,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;gBACpD,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAgB,EAAE,CAAC;YAChE,CAAC;QACH,CAAC;QAED,4CAA4C;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACxD,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAE3E,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,EAAU;QACpC,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IAEO,cAAc,CACpB,KAAa,EACb,IAAwB,EACxB,SAAmD;QAEnD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAC5D,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC5C,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YACjC,OAAO,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAClD,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,YAAY;QAClB,OAAO,sCAAsC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE;YACjE,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACjC,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,iCAAiC;IACzB,WAAW,CAAC,GAAW;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpD,OAAO,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED,4DAA4D;IACpD,OAAO,CAAC,GAAW;QACzB,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpD,OAAO,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IAC9B,CAAC;CACF"}
@@ -0,0 +1,49 @@
1
+ import { FieldDelta } from './local_datastore.js';
2
+ export type { FieldDelta };
3
+ export interface Change {
4
+ type: 'insert' | 'update' | 'delete';
5
+ table: string;
6
+ id?: string;
7
+ data?: any;
8
+ deltas?: Record<string, FieldDelta>;
9
+ baseRev?: string;
10
+ timestamp: number;
11
+ }
12
+ export type ConflictStrategy = 'last-write-wins' | 'soma-delta' | 'manual';
13
+ export interface ConflictRecord {
14
+ id: string;
15
+ tabela: string;
16
+ registroId: string;
17
+ camposConflitantes: string[];
18
+ deltasLocais: Record<string, FieldDelta>;
19
+ valorLocal: any;
20
+ valorServidor: any;
21
+ timestamp: string;
22
+ resolvido: boolean;
23
+ }
24
+ export declare class ConflictManager {
25
+ private conflitos;
26
+ mergeFields(serverRecord: any, deltas: Record<string, FieldDelta>): {
27
+ merged: any;
28
+ conflitantes: string[];
29
+ };
30
+ registrar(tabela: string, registroId: string, deltasLocais: Record<string, FieldDelta>, valorLocal: any, valorServidor: any, camposConflitantes: string[]): ConflictRecord;
31
+ resolver(conflito: ConflictRecord, strategy: ConflictStrategy): any;
32
+ pendentes(): ConflictRecord[];
33
+ resolverManualmente(conflitoid: string, valorEscolhido: any): void;
34
+ total(): number;
35
+ totalResolvidos(): number;
36
+ }
37
+ export declare class SyncManager {
38
+ private queue;
39
+ private isOnline;
40
+ private serverUrl;
41
+ private syncing;
42
+ readonly conflicts: ConflictManager;
43
+ constructor(serverUrl?: string);
44
+ queueChange(change: Omit<Change, 'timestamp'>): Promise<void>;
45
+ pendingCount(): number;
46
+ private processQueue;
47
+ private sendToServer;
48
+ }
49
+ //# sourceMappingURL=sync_manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync_manager.d.ts","sourceRoot":"","sources":["../../persistence/sync_manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,YAAY,GAAG,QAAQ,CAAC;AAE3E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACzC,UAAU,EAAE,GAAG,CAAC;IAChB,aAAa,EAAE,GAAG,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAwB;IAUzC,WAAW,CACT,YAAY,EAAE,GAAG,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GACjC;QAAE,MAAM,EAAE,GAAG,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE;IA6B1C,SAAS,CACP,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EACxC,UAAU,EAAE,GAAG,EACf,aAAa,EAAE,GAAG,EAClB,kBAAkB,EAAE,MAAM,EAAE,GAC3B,cAAc;IAkBjB,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,GAAG,GAAG;IAiCnE,SAAS,IAAI,cAAc,EAAE;IAI7B,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,GAAG,IAAI;IAKlE,KAAK,IAAI,MAAM;IACf,eAAe,IAAI,MAAM;CAC1B;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,QAAQ,CAEP;IACT,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAkB;IAGjC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAyB;gBAEhD,SAAS,GAAE,MAAoB;IAarC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnE,YAAY,IAAI,MAAM;YAIR,YAAY;YA0DZ,YAAY;CAqB3B"}
@@ -0,0 +1,187 @@
1
+ export class ConflictManager {
2
+ conflitos = [];
3
+ // Tenta merge automático campo a campo.
4
+ //
5
+ // Para cada campo em `deltas`:
6
+ // - Se o servidor não mexeu nesse campo (valor atual == delta.de) → aplica delta.para
7
+ // - Se é numérico e ambos mexeram → aplica o delta relativo (soma-delta correta)
8
+ // - Se é não-numérico e ambos mexeram → conflito real, precisa resolução humana
9
+ //
10
+ // Retorna o registro mesclado e a lista de campos que não puderam ser resolvidos.
11
+ mergeFields(serverRecord, deltas) {
12
+ const merged = { ...serverRecord };
13
+ const conflitantes = [];
14
+ for (const [campo, delta] of Object.entries(deltas)) {
15
+ const valorServidorAtual = serverRecord[campo];
16
+ if (valorServidorAtual === delta.de) {
17
+ // Servidor não alterou este campo — aplicar mudança do cliente sem conflito
18
+ merged[campo] = delta.para;
19
+ }
20
+ else if (typeof valorServidorAtual === 'number' &&
21
+ typeof delta.de === 'number' &&
22
+ typeof delta.para === 'number') {
23
+ // Ambos alteraram um campo numérico — aplicar delta relativo
24
+ // Exemplo: base=12, A vendeu 2 (delta=-2), servidor já tem 8 (B vendeu 4)
25
+ // Resultado: 8 + (10 - 12) = 8 - 2 = 6 ✓
26
+ const deltaNominal = delta.para - delta.de;
27
+ merged[campo] = valorServidorAtual + deltaNominal;
28
+ }
29
+ else {
30
+ // Campo não-numérico editado pelos dois lados → conflito real
31
+ conflitantes.push(campo);
32
+ }
33
+ }
34
+ return { merged, conflitantes };
35
+ }
36
+ registrar(tabela, registroId, deltasLocais, valorLocal, valorServidor, camposConflitantes) {
37
+ const conflito = {
38
+ id: `conflict_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,
39
+ tabela,
40
+ registroId,
41
+ camposConflitantes,
42
+ deltasLocais,
43
+ valorLocal,
44
+ valorServidor,
45
+ timestamp: new Date().toISOString(),
46
+ resolvido: false
47
+ };
48
+ this.conflitos.push(conflito);
49
+ return conflito;
50
+ }
51
+ // Resolve um conflito pendente com a estratégia escolhida.
52
+ // Retorna o valor final a ser reenviado ao servidor.
53
+ resolver(conflito, strategy) {
54
+ switch (strategy) {
55
+ case 'last-write-wins':
56
+ // Aplica todos os deltas do cliente sobre o estado do servidor
57
+ const resultLww = { ...conflito.valorServidor };
58
+ for (const [campo, delta] of Object.entries(conflito.deltasLocais)) {
59
+ resultLww[campo] = delta.para;
60
+ }
61
+ return resultLww;
62
+ case 'soma-delta':
63
+ // Para numéricos: aplica delta relativo sobre o valor atual do servidor
64
+ // Para não-numéricos em conflito: LWW (cliente vence)
65
+ const resultDelta = { ...conflito.valorServidor };
66
+ for (const [campo, delta] of Object.entries(conflito.deltasLocais)) {
67
+ const srv = conflito.valorServidor[campo];
68
+ if (typeof srv === 'number' &&
69
+ typeof delta.de === 'number' &&
70
+ typeof delta.para === 'number') {
71
+ resultDelta[campo] = srv + (delta.para - delta.de);
72
+ }
73
+ else {
74
+ resultDelta[campo] = delta.para;
75
+ }
76
+ }
77
+ return resultDelta;
78
+ case 'manual':
79
+ return null; // aguarda resolverManualmente()
80
+ }
81
+ }
82
+ pendentes() {
83
+ return this.conflitos.filter(c => !c.resolvido);
84
+ }
85
+ resolverManualmente(conflitoid, valorEscolhido) {
86
+ const conflito = this.conflitos.find(c => c.id === conflitoid);
87
+ if (conflito)
88
+ conflito.resolvido = true;
89
+ }
90
+ total() { return this.conflitos.length; }
91
+ totalResolvidos() { return this.conflitos.filter(c => c.resolvido).length; }
92
+ }
93
+ export class SyncManager {
94
+ queue = [];
95
+ isOnline = typeof navigator !== 'undefined'
96
+ ? navigator.onLine
97
+ : true;
98
+ serverUrl;
99
+ syncing = false;
100
+ // Público para que o código da aplicação possa consultar conflitos pendentes
101
+ conflicts = new ConflictManager();
102
+ constructor(serverUrl = '/api/sync') {
103
+ this.serverUrl = serverUrl;
104
+ if (typeof window !== 'undefined') {
105
+ window.addEventListener('online', () => {
106
+ this.isOnline = true;
107
+ this.processQueue();
108
+ });
109
+ window.addEventListener('offline', () => {
110
+ this.isOnline = false;
111
+ });
112
+ }
113
+ }
114
+ async queueChange(change) {
115
+ this.queue.push({ ...change, timestamp: Date.now() });
116
+ if (this.isOnline) {
117
+ await this.processQueue();
118
+ }
119
+ }
120
+ pendingCount() {
121
+ return this.queue.length;
122
+ }
123
+ async processQueue() {
124
+ if (this.syncing || this.queue.length === 0)
125
+ return;
126
+ this.syncing = true;
127
+ while (this.queue.length > 0 && this.isOnline) {
128
+ const change = this.queue[0];
129
+ try {
130
+ await this.sendToServer(change);
131
+ this.queue.shift();
132
+ }
133
+ catch (err) {
134
+ if (err?.status === 409 && err?.serverRecord && change.deltas) {
135
+ // Servidor tem versão diferente — tentar merge automático
136
+ const { merged, conflitantes } = this.conflicts.mergeFields(err.serverRecord, change.deltas);
137
+ if (conflitantes.length === 0) {
138
+ // Merge automático bem-sucedido: atualizar a mudança na fila
139
+ // com o novo baseRev e os deltas já reconciliados
140
+ this.queue[0] = {
141
+ ...change,
142
+ baseRev: err.serverRecord._rev,
143
+ deltas: Object.fromEntries(Object.entries(change.deltas).map(([campo, delta]) => [
144
+ campo,
145
+ { de: err.serverRecord[campo], para: merged[campo] }
146
+ ]))
147
+ };
148
+ // Continua o loop — vai tentar enviar novamente
149
+ continue;
150
+ }
151
+ else {
152
+ // Conflito real em campos não-numéricos — registrar e remover da fila
153
+ // A aplicação deve consultar conflicts.pendentes() e chamar
154
+ // syncManager.conflicts.resolverManualmente()
155
+ this.conflicts.registrar(change.table, change.id, change.deltas, Object.fromEntries(Object.entries(change.deltas).map(([k, d]) => [k, d.para])), err.serverRecord, conflitantes);
156
+ this.queue.shift();
157
+ }
158
+ }
159
+ else {
160
+ // Erro de rede ou servidor — manter na fila, tentar depois
161
+ break;
162
+ }
163
+ }
164
+ }
165
+ this.syncing = false;
166
+ }
167
+ async sendToServer(change) {
168
+ const response = await fetch(this.serverUrl, {
169
+ method: 'POST',
170
+ headers: { 'Content-Type': 'application/json' },
171
+ body: JSON.stringify(change)
172
+ });
173
+ if (response.status === 409) {
174
+ // Servidor detectou conflito de versão (_rev divergiu)
175
+ // Corpo esperado: { serverRecord: { ...registro atual... } }
176
+ const body = await response.json();
177
+ const err = new Error('Conflito de versão detectado');
178
+ err.status = 409;
179
+ err.serverRecord = body.serverRecord;
180
+ throw err;
181
+ }
182
+ if (!response.ok) {
183
+ throw new Error(`Sync falhou: ${response.statusText}`);
184
+ }
185
+ }
186
+ }
187
+ //# sourceMappingURL=sync_manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync_manager.js","sourceRoot":"","sources":["../../persistence/sync_manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface PWAConfig {
2
+ nome: string;
3
+ nomeAbreviado?: string;
4
+ descricao?: string;
5
+ icone?: string;
6
+ cor_tema?: string;
7
+ cor_fundo?: string;
8
+ offline?: boolean;
9
+ arquivosCache?: string[];
10
+ }
11
+ export declare class PWAGenerator {
12
+ gerarManifest(config: PWAConfig): string;
13
+ gerarServiceWorker(config: PWAConfig): string;
14
+ gerarIndexHTML(config: PWAConfig): string;
15
+ }
16
+ //# sourceMappingURL=pwa_generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pwa_generator.d.ts","sourceRoot":"","sources":["../../pwa/pwa_generator.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,qBAAa,YAAY;IACvB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM;IAyBxC,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM;IAsD7C,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM;CA4B1C"}