muya 2.5.3 → 2.5.5

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 (134) hide show
  1. package/{src/__tests__ → __tests__}/bench.test.tsx +4 -4
  2. package/{src/__tests__ → __tests__}/compare.test.tsx +8 -6
  3. package/{src/__tests__ → __tests__}/create.test.tsx +2 -2
  4. package/{src/utils/__tests__ → __tests__}/is.test.ts +3 -3
  5. package/{src/__tests__ → __tests__}/scheduler.test.tsx +1 -1
  6. package/{src/__tests__ → __tests__}/select.test.tsx +5 -5
  7. package/{src/utils/__tests__ → __tests__}/shallow.test.ts +1 -1
  8. package/{src/__tests__ → __tests__}/use-value-loadable.test.tsx +3 -3
  9. package/{src/__tests__ → __tests__}/use-value.test.tsx +8 -8
  10. package/build.ts +67 -0
  11. package/dist/cjs/index.js +1 -0
  12. package/dist/esm/create.js +1 -0
  13. package/dist/esm/debug/development-tools.js +1 -0
  14. package/dist/esm/index.js +1 -0
  15. package/dist/esm/select.js +1 -0
  16. package/{types → dist/types}/create-state.d.ts +1 -0
  17. package/dist/types/create-state.d.ts.map +1 -0
  18. package/{types → dist/types}/create.d.ts +1 -0
  19. package/dist/types/create.d.ts.map +1 -0
  20. package/dist/types/debug/development-tools.d.ts +13 -0
  21. package/dist/types/debug/development-tools.d.ts.map +1 -0
  22. package/{types → dist/types}/index.d.ts +3 -1
  23. package/dist/types/index.d.ts.map +1 -0
  24. package/{types → dist/types}/scheduler.d.ts +1 -0
  25. package/dist/types/scheduler.d.ts.map +1 -0
  26. package/{types → dist/types}/select.d.ts +1 -0
  27. package/dist/types/select.d.ts.map +1 -0
  28. package/{types → dist/types}/types.d.ts +1 -0
  29. package/dist/types/types.d.ts.map +1 -0
  30. package/{types → dist/types}/use-value-loadable.d.ts +1 -0
  31. package/dist/types/use-value-loadable.d.ts.map +1 -0
  32. package/{types → dist/types}/use-value.d.ts +2 -1
  33. package/dist/types/use-value.d.ts.map +1 -0
  34. package/{types → dist/types}/utils/common.d.ts +1 -0
  35. package/dist/types/utils/common.d.ts.map +1 -0
  36. package/{types → dist/types}/utils/create-emitter.d.ts +1 -0
  37. package/dist/types/utils/create-emitter.d.ts.map +1 -0
  38. package/{types → dist/types}/utils/id.d.ts +1 -0
  39. package/dist/types/utils/id.d.ts.map +1 -0
  40. package/{types → dist/types}/utils/is.d.ts +1 -0
  41. package/dist/types/utils/is.d.ts.map +1 -0
  42. package/{types → dist/types}/utils/shallow.d.ts +1 -0
  43. package/dist/types/utils/shallow.d.ts.map +1 -0
  44. package/package.json +23 -8
  45. package/src/create-state.d.ts.map +1 -0
  46. package/src/create.d.ts.map +1 -0
  47. package/src/create.ts +7 -2
  48. package/src/debug/development-tools.d.ts.map +1 -0
  49. package/src/debug/development-tools.ts +5 -40
  50. package/src/index.d.ts.map +1 -0
  51. package/src/index.ts +2 -1
  52. package/src/scheduler.d.ts.map +1 -0
  53. package/src/select.d.ts.map +1 -0
  54. package/src/select.ts +7 -2
  55. package/src/types.d.ts.map +1 -0
  56. package/src/use-value-loadable.d.ts.map +1 -0
  57. package/src/use-value.d.ts.map +1 -0
  58. package/src/use-value.ts +1 -1
  59. package/src/utils/common.d.ts.map +1 -0
  60. package/src/utils/create-emitter.d.ts.map +1 -0
  61. package/src/utils/id.d.ts.map +1 -0
  62. package/src/utils/is.d.ts.map +1 -0
  63. package/src/utils/shallow.d.ts.map +1 -0
  64. package/tsconfig.build.json +12 -0
  65. package/cjs/index.js +0 -1
  66. package/esm/__tests__/test-utils.js +0 -1
  67. package/esm/create.js +0 -1
  68. package/esm/debug/development-tools.js +0 -1
  69. package/esm/index.js +0 -1
  70. package/esm/select.js +0 -1
  71. package/esm/sqlite/__tests__/create-sqlite.test.js +0 -1
  72. package/esm/sqlite/__tests__/map-deque.test.js +0 -1
  73. package/esm/sqlite/__tests__/table.test.js +0 -1
  74. package/esm/sqlite/__tests__/tokenizer.test.js +0 -1
  75. package/esm/sqlite/__tests__/where.test.js +0 -1
  76. package/esm/sqlite/create-sqlite.js +0 -1
  77. package/esm/sqlite/index.js +0 -1
  78. package/esm/sqlite/table/backend.js +0 -1
  79. package/esm/sqlite/table/bun-backend.js +0 -1
  80. package/esm/sqlite/table/index.js +0 -1
  81. package/esm/sqlite/table/map-deque.js +0 -1
  82. package/esm/sqlite/table/table.js +0 -43
  83. package/esm/sqlite/table/table.types.js +0 -0
  84. package/esm/sqlite/table/tokenizer.js +0 -1
  85. package/esm/sqlite/table/where.js +0 -1
  86. package/esm/sqlite/use-sqlite-count.js +0 -1
  87. package/esm/sqlite/use-sqlite.js +0 -1
  88. package/esm/utils/__tests__/is.test.js +0 -1
  89. package/esm/utils/__tests__/shallow.test.js +0 -1
  90. package/src/sqlite/__tests__/create-sqlite.test.ts +0 -264
  91. package/src/sqlite/__tests__/map-deque.test.ts +0 -61
  92. package/src/sqlite/__tests__/table.test.ts +0 -351
  93. package/src/sqlite/__tests__/tokenizer.test.ts +0 -43
  94. package/src/sqlite/__tests__/use-slite-count.test.tsx +0 -96
  95. package/src/sqlite/__tests__/use-sqlite.more.test.tsx +0 -637
  96. package/src/sqlite/__tests__/use-sqlite.test.tsx +0 -1008
  97. package/src/sqlite/__tests__/where.test.ts +0 -234
  98. package/src/sqlite/create-sqlite.ts +0 -164
  99. package/src/sqlite/index.ts +0 -4
  100. package/src/sqlite/table/backend.ts +0 -21
  101. package/src/sqlite/table/bun-backend.ts +0 -47
  102. package/src/sqlite/table/index.ts +0 -6
  103. package/src/sqlite/table/map-deque.ts +0 -29
  104. package/src/sqlite/table/table.ts +0 -353
  105. package/src/sqlite/table/table.types.ts +0 -129
  106. package/src/sqlite/table/tokenizer.ts +0 -35
  107. package/src/sqlite/table/where.ts +0 -207
  108. package/src/sqlite/use-sqlite-count.ts +0 -69
  109. package/src/sqlite/use-sqlite.ts +0 -250
  110. package/types/__tests__/test-utils.d.ts +0 -25
  111. package/types/debug/development-tools.d.ts +0 -8
  112. package/types/sqlite/create-sqlite.d.ts +0 -31
  113. package/types/sqlite/index.d.ts +0 -4
  114. package/types/sqlite/table/backend.d.ts +0 -20
  115. package/types/sqlite/table/bun-backend.d.ts +0 -6
  116. package/types/sqlite/table/index.d.ts +0 -6
  117. package/types/sqlite/table/map-deque.d.ts +0 -5
  118. package/types/sqlite/table/table.d.ts +0 -21
  119. package/types/sqlite/table/table.types.d.ts +0 -91
  120. package/types/sqlite/table/tokenizer.d.ts +0 -11
  121. package/types/sqlite/table/where.d.ts +0 -37
  122. package/types/sqlite/use-sqlite-count.d.ts +0 -17
  123. package/types/sqlite/use-sqlite.d.ts +0 -39
  124. /package/{src/__tests__ → __tests__}/test-utils.ts +0 -0
  125. /package/{esm → dist/esm}/create-state.js +0 -0
  126. /package/{esm → dist/esm}/scheduler.js +0 -0
  127. /package/{esm → dist/esm}/types.js +0 -0
  128. /package/{esm → dist/esm}/use-value-loadable.js +0 -0
  129. /package/{esm → dist/esm}/use-value.js +0 -0
  130. /package/{esm → dist/esm}/utils/common.js +0 -0
  131. /package/{esm → dist/esm}/utils/create-emitter.js +0 -0
  132. /package/{esm → dist/esm}/utils/id.js +0 -0
  133. /package/{esm → dist/esm}/utils/is.js +0 -0
  134. /package/{esm → dist/esm}/utils/shallow.js +0 -0
package/src/index.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export * from './utils/is'
2
2
  export * from './types'
3
- export { create } from './create'
3
+ export { create, STATE_SCHEDULER } from './create'
4
4
  export { select } from './select'
5
5
  export { useValue } from './use-value'
6
6
  export { useValueLoadable, type LoadableResult } from './use-value-loadable'
7
7
  export { shallow } from './utils/shallow'
8
+ export { getId } from './utils/id'
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["scheduler.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,MAAM,CAAA;AAC5B,eAAO,MAAM,eAAe,KAAK,CAAA;AACjC,eAAO,MAAM,gBAAgB,IAAI,CAAA;AAEjC,KAAK,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;AAM1C,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAA;IAC1C,QAAQ,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACtE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe;QAmEvB,CAAC,MAAM,UAAU,UAAU,gBAAgB,CAAC,CAAC,CAAC;aAMzC,CAAC,MAAM,UAAU,SAAS,CAAC;EAKvC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["select.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAIhD,KAAK,iBAAiB,CAAC,CAAC,SAAS,KAAK,CAAC,OAAO,CAAC,IAAI;KAChD,CAAC,IAAI,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;CACxC,CAAA;AAED,KAAK,YAAY,CAAC,CAAC,SAAS,KAAK,CAAC,OAAO,CAAC,IAAI;KAC3C,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC9B,CAAA;AACD;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,EAC/D,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC5B,QAAQ,EAAE,CAAC,GAAG,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,EAC3C,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GACnB,QAAQ,CAAC,CAAC,CAAC,CA+Gb"}
package/src/select.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { STATE_SCHEDULER } from './create'
2
2
  import { createState } from './create-state'
3
- import { subscribeToDevelopmentTools } from './debug/development-tools'
3
+ import { sendToDevtools } from './debug/development-tools'
4
4
  import type { GetState, IsEqual } from './types'
5
5
  import { AbortError, canUpdate, handleAsyncUpdate } from './utils/common'
6
6
  import { isPromise, isUndefined } from './utils/is'
@@ -124,9 +124,14 @@ export function select<T = unknown, S extends Array<unknown> = []>(
124
124
  return
125
125
  }
126
126
  state.emitter.emit()
127
+ sendToDevtools({
128
+ name: state.stateName ?? `derived(${state.id})`,
129
+ type: 'derived',
130
+ value: state.cache.current,
131
+ message: 'update',
132
+ })
127
133
  },
128
134
  })
129
135
 
130
- subscribeToDevelopmentTools(state)
131
136
  return state
132
137
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAErD,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;AAC1D,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAC7D,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AACpD,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;AAC3C,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;AACtE,MAAM,WAAW,KAAK,CAAC,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,CAAA;IACX,QAAQ,CAAC,EAAE,CAAC,CAAA;IACZ,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC;AAED,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,KAA8B,CAAC,CAAA;AAEjF,MAAM,WAAW,QAAQ,CAAC,CAAC,EAAE,aAAa,SAAS,OAAO,GAAG,KAAK;IAChE,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,SAAS,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACnF;;OAEG;IACH,GAAG,EAAE,MAAM,aAAa,SAAS,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACtD;;OAEG;IACH,EAAE,EAAE,MAAM,CAAA;IACV;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB;;OAEG;IACH,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5B;;;OAGG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAA;IACvC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,MAAM,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC,CAAA;CAChI;AAED,MAAM,WAAW,KAAK,CAAC,CAAC,CAAE,SAAQ,QAAQ,CAAC,CAAC,CAAC;IAC3C;;;;OAIG;IACH,GAAG,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IACjC;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,CAAA;IACpC,KAAK,EAAE,IAAI,CAAA;IACX,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;CAChB"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-value-loadable.d.ts","sourceRoot":"","sources":["use-value-loadable.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGvD,KAAK,eAAe,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAA;AAC1D,KAAK,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAA;AACtD,KAAK,aAAa,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;AAEpD,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,aAAa,CAAA;AAEpF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,EAC/C,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAClB,QAAQ,GAAE,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAkB,GACvD,cAAc,CAAC,SAAS,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAkBtD"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-value.d.ts","sourceRoot":"","sources":["use-value.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIvD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAC3B,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAClB,QAAQ,GAAE,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAkB,GACvD,SAAS,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAkBtC"}
package/src/use-value.ts CHANGED
@@ -8,7 +8,7 @@ import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/w
8
8
  * @param state The state to subscribe to
9
9
  * @param selector Optional function to derive a value from the state
10
10
  * @returns The current value of the state or the derived value from the selector
11
- * @throws If the value is a Promise or an Error, it will be thrown to be handled by an error boundary or suspense
11
+ * @throws {Promise | Error} If the value is a Promise or an Error, it will be thrown to be handled by an error boundary or suspense
12
12
  */
13
13
  export function useValue<T, S>(
14
14
  state: GetState<T>,
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["common.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAGrD,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB,UAAU,CAAC,EAAE,eAAe,CAAA;CAC7B;AAED,qBAAa,UAAW,SAAQ,KAAK;IACnC,MAAM,CAAC,QAAQ,CAAC,KAAK,gBAAe;CACrC;AACD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAAC,EAAE,eAAe,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAgBpH;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,OAAO,CAAC,CAAC,CAAe,GAAG,OAAO,CAQxF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CA2BjE"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-emitter.d.ts","sourceRoot":"","sources":["create-emitter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,CAAC,CAAC,GAAG,SAAS,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;AAChG,MAAM,WAAW,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS;IACvC,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAC9B,uBAAuB,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;IAC5D,WAAW,EAAE,MAAM,CAAC,CAAA;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC,CAAA;IAC5B,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,KAAK,IAAI,CAAA;IAC9B,OAAO,EAAE,MAAM,MAAM,CAAA;IACrB,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,KAAK,IAAI,KAAK,OAAO,CAAA;CAC1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,kBAAkB,CAAC,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAkCjH"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["id.ts"],"names":[],"mappings":"AACA;;;GAGG;AACH,wBAAgB,KAAK,IAAI,MAAM,CAG9B"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is.d.ts","sourceRoot":"","sources":["is.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAErC,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAEhE;AAED,wBAAgB,UAAU,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,CAAC,CAEhG;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAEpE;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAE3D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAE/D;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAK5D;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,CAEhF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAEhE;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAEtD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAE9D;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,CAE5D"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shallow.d.ts","sourceRoot":"","sources":["shallow.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAmDxD"}
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "outDir": "./dist/types",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "emitDeclarationOnly": true
9
+ },
10
+ "include": ["./src/**/*.ts", "./src/**/*.tsx"],
11
+ "exclude": ["node_modules", "**/__tests__/**"]
12
+ }
package/cjs/index.js DELETED
@@ -1 +0,0 @@
1
- "use strict";var O=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var W=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var Q=(e,t)=>{for(var n in t)O(e,n,{get:t[n],enumerable:!0})},X=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of W(t))!J.call(e,s)&&s!==n&&O(e,s,{get:()=>t[s],enumerable:!(a=Y(t,s))||a.enumerable});return e};var Z=e=>X(O({},"__esModule",{value:!0}),e);var ee={};Q(ee,{EMPTY_SELECTOR:()=>w,create:()=>F,isAbortError:()=>v,isArray:()=>k,isEqualBase:()=>S,isError:()=>b,isFunction:()=>h,isMap:()=>g,isPromise:()=>l,isSet:()=>P,isSetValueFunction:()=>D,isState:()=>B,isUndefined:()=>f,select:()=>V,shallow:()=>j,useValue:()=>C,useValueLoadable:()=>_});module.exports=Z(ee);var T=class extends Error{static Error="AbortError"};function $(e,t){t&&t.abort();let n=new AbortController,{signal:a}=n;return{promise:new Promise((o,c)=>{a.addEventListener("abort",()=>{c(new T)}),e.then(o).catch(c)}),controller:n}}function E(e,t=S){if(!f(e.current)){if(!f(e.previous)&&t(e.current,e.previous))return!1;e.previous=e.current}return!0}function p(e,t){let{cache:n,emitter:{emit:a}}=e;if(!l(t))return t;n.abortController&&n.abortController.abort();let{promise:s,controller:o}=$(t,n.abortController);return n.abortController=o,s.then(c=>{n.current=c,a()}).catch(c=>{v(c)||(n.current=c,a())})}function l(e){return e instanceof Promise}function h(e){return typeof e=="function"}function g(e){return e instanceof Map}function P(e){return e instanceof Set}function k(e){return Array.isArray(e)}function S(e,t){return e===t?!0:!!Object.is(e,t)}function D(e){return typeof e=="function"}function v(e){return e instanceof T}function b(e){return e instanceof Error}function f(e){return e===void 0}function B(e){return h(e)&&"get"in e&&"set"in e&&"isSet"in e&&e.isSet===!0}var w=e=>e;function G(){let e=new Map,t=new Set,n=performance.now(),a=!1;function s(){let c=performance.now(),r=c-n,{size:i}=t;if(r<.2&&i>0&&i<10){n=c,o();return}a||(a=!0,Promise.resolve().then(()=>{a=!1,n=performance.now(),o()}))}function o(){if(t.size===0)return;let c=new Set,r=new Map;for(let i of t){if(e.has(i.id)){c.add(i.id);let{onResolveItem:u}=e.get(i.id);u&&u(i.value),r.has(i.id)||r.set(i.id,[]),r.get(i.id).push(i.value)}t.delete(i)}if(t.size>0){s();return}for(let i of c){let u=r.get(i);e.get(i)?.onScheduleDone(u)}}return{add(c,r){return e.set(c,r),()=>{e.delete(c)}},schedule(c,r){t.add({value:r,id:c}),s()}}}function V(e,t,n){function a(){let u=!1,d=e.map(L=>{let x=L.get();return l(x)&&(u=!0),x});return u?new Promise((L,x)=>{Promise.all(d).then(R=>{if(R.some(K=>f(K)))return x(new T);let N=t(...R);L(N)})}):t(...d)}function s(){if(f(r.cache.current)){let u=a();r.cache.current=p(r,u)}return r.cache.current}function o(){if(f(r.cache.current)){let d=a();r.cache.current=p(r,d)}let{current:u}=r.cache;return l(u)?new Promise(d=>{u.then(m=>{if(f(m)){d(o());return}d(m)})}):r.cache.current}let c=[];for(let u of e){let d=u.emitter.subscribe(()=>{y.schedule(r.id,null)});c.push(d)}let r=A({destroy(){for(let u of c)u();i(),r.emitter.clear(),r.cache.current=void 0},get:o,getSnapshot:s}),i=y.add(r.id,{onScheduleDone(){let u=a();r.cache.current=p(r,u),E(r.cache,n)&&r.emitter.emit()}});return r}var U=require("react");var M=require("use-sync-external-store/shim/with-selector");function C(e,t=w){let{emitter:n}=e,a=(0,M.useSyncExternalStoreWithSelector)(e.emitter.subscribe,n.getSnapshot,n.getInitialSnapshot,t);if((0,U.useDebugValue)(a),l(a)||b(a))throw a;return a}function q(e,t){let n=new Set,a=[];return{clear:()=>{for(let s of a)s();n.clear()},subscribe:s=>(n.add(s),()=>{n.delete(s)}),emit:(...s)=>{for(let o of n)o(...s)},contains:s=>n.has(s),getSnapshot:e,getInitialSnapshot:t,getSize:()=>n.size,subscribeToOtherEmitter(s){let o=s.subscribe(()=>{this.emit()});a.push(o)}}}var H=0;function z(){return H++,H.toString(36)}function A(e){let{get:t,destroy:n,set:a,getSnapshot:s}=e,o=!!a,c={},r=function(i){return C(r,i)};return r.isSet=o,r.id=z(),r.emitter=q(s),r.destroy=n,r.listen=function(i){return this.emitter.subscribe(()=>{let u=t();l(u)||i(t())})},r.withName=function(i){return this.stateName=i,this},r.select=function(i,u=S){return V([r],i,u)},r.get=t,r.set=a,r.cache=c,r}var y=G();function F(e,t=S){function n(){try{if(f(o.cache.current)){let r=h(e)?e():e,i=p(o,r);return o.cache.current=i,o.cache.current}return o.cache.current}catch(r){o.cache.current=r}return o.cache.current}async function a(r,i){await r;let u=i(o.cache.current),d=p(o,u);o.cache.current=d}function s(r){let i=n(),u=D(r);if(u&&l(i)){a(i,r);return}o.cache.abortController&&o.cache.abortController.abort();let d=u?r(i):r,m=p(o,d);o.cache.current=m}let o=A({get:n,destroy(){n(),c(),o.emitter.clear(),o.cache.current=void 0},set(r){y.schedule(o.id,r)},getSnapshot:n}),c=y.add(o.id,{onScheduleDone(){o.cache.current=n(),E(o.cache,t)&&o.emitter.emit()},onResolveItem:s});return h(e)||n(),o}var I=require("react");function _(e,t=w){let{emitter:n}=e,a=(0,I.useSyncExternalStore)(n.subscribe,n.getSnapshot,n.getInitialSnapshot);return(0,I.useDebugValue)(a),l(a)?[void 0,!0,!1,void 0]:b(a)?[void 0,!1,!0,a]:[t(a),!1,!1,void 0]}function j(e,t){if(e==t)return!0;if(typeof e!="object"||e==null||typeof t!="object"||t==null)return!1;if(g(e)&&g(t)){if(e.size!==t.size)return!1;for(let[s,o]of e)if(!Object.is(o,t.get(s)))return!1;return!0}if(P(e)&&P(t)){if(e.size!==t.size)return!1;for(let s of e)if(!t.has(s))return!1;return!0}if(k(e)&&k(t)){if(e.length!==t.length)return!1;for(let[s,o]of e.entries())if(!Object.is(o,t[s]))return!1;return!0}let n=Object.keys(e),a=Object.keys(t);if(n.length!==a.length)return!1;for(let s of n)if(!Object.prototype.hasOwnProperty.call(t,s)||!Object.is(e[s],t[s]))return!1;return!0}
@@ -1 +0,0 @@
1
- import{Component as t}from"react";function n(e=200){return new Promise(r=>{setTimeout(()=>{r(0)},e)})}class c extends t{constructor(r){super(r),this.state={hasError:!1,error:null}}static getDerivedStateFromError(r){return{hasError:!0,error:r}}componentDidCatch(r,o){console.error("ErrorBoundary caught an error:",r,o)}render(){return this.state.hasError?this.props.fallback:this.props.children}}export{c as ErrorBoundary,n as longPromise};
package/esm/create.js DELETED
@@ -1 +0,0 @@
1
- import{canUpdate as S,handleAsyncUpdate as u}from"./utils/common";import{isEqualBase as T,isFunction as s,isPromise as p,isSetValueFunction as V,isUndefined as b}from"./utils/is";import{createScheduler as y}from"./scheduler";import{subscribeToDevelopmentTools as E}from"./debug/development-tools";import{createState as w}from"./create-state";const i=y();function g(a,l=T){function c(){try{if(b(e.cache.current)){const t=s(a)?a():a,r=u(e,t);return e.cache.current=r,e.cache.current}return e.cache.current}catch(t){e.cache.current=t}return e.cache.current}async function d(t,r){await t;const n=r(e.cache.current),o=u(e,n);e.cache.current=o}function h(t){const r=c(),n=V(t);if(n&&p(r)){d(r,t);return}e.cache.abortController&&e.cache.abortController.abort();const o=n?t(r):t,f=u(e,o);e.cache.current=f}const e=w({get:c,destroy(){c(),m(),e.emitter.clear(),e.cache.current=void 0},set(t){i.schedule(e.id,t)},getSnapshot:c}),m=i.add(e.id,{onScheduleDone(){e.cache.current=c(),S(e.cache,l)&&e.emitter.emit()},onResolveItem:h});return s(a)||c(),E(e),e}export{i as STATE_SCHEDULER,g as create};
@@ -1 +0,0 @@
1
- import{isPromise as r,isState as a}from"../utils/is";const o=globalThis?.__REDUX_DEVTOOLS_EXTENSION__?.connect({name:"CustomState",trace:!0});o&&o.init({message:"Initial state"});function p(e){if(!o)return;const{message:t,type:n,value:s,name:i}=e;r(s)||o.send(i,{value:s,type:n,message:t},n)}function m(e,t){return n=>{p({name:e,type:t,value:n,message:"update"})}}function l(e){}export{l as subscribeToDevelopmentTools};
package/esm/index.js DELETED
@@ -1 +0,0 @@
1
- export*from"./utils/is";export*from"./types";import{create as a}from"./create";import{select as p}from"./select";import{useValue as m}from"./use-value";import{useValueLoadable as s}from"./use-value-loadable";import{shallow as b}from"./utils/shallow";export{a as create,p as select,b as shallow,m as useValue,s as useValueLoadable};
package/esm/select.js DELETED
@@ -1 +0,0 @@
1
- import{STATE_SCHEDULER as p}from"./create";import{createState as k}from"./create-state";import{subscribeToDevelopmentTools as b}from"./debug/development-tools";import{AbortError as E,canUpdate as D,handleAsyncUpdate as s}from"./utils/common";import{isPromise as T,isUndefined as c}from"./utils/is";function U(i,d,h){function o(){let t=!1;const n=i.map(u=>{const r=u.get();return T(r)&&(t=!0),r});return t?new Promise((u,r)=>{Promise.all(n).then(m=>{if(m.some(A=>c(A)))return r(new E);const w=d(...m);u(w)})}):d(...n)}function S(){if(c(e.cache.current)){const t=o();e.cache.current=s(e,t)}return e.cache.current}function f(){if(c(e.cache.current)){const n=o();e.cache.current=s(e,n)}const{current:t}=e.cache;return T(t)?new Promise(n=>{t.then(a=>{if(c(a)){n(f());return}n(a)})}):e.cache.current}const l=[];for(const t of i){const n=t.emitter.subscribe(()=>{p.schedule(e.id,null)});l.push(n)}const e=k({destroy(){for(const t of l)t();y(),e.emitter.clear(),e.cache.current=void 0},get:f,getSnapshot:S}),y=p.add(e.id,{onScheduleDone(){const t=o();e.cache.current=s(e,t),D(e.cache,h)&&e.emitter.emit()}});return b(e),e}export{U as select};
@@ -1 +0,0 @@
1
- import{createSqliteState as i}from"../create-sqlite";import{bunMemoryBackend as p}from"../table/bun-backend";const c=p();describe("create-sqlite-state",()=>{it("should batchSet and update multiple documents",async()=>{const e=i({backend:c,tableName:"State2",key:"id"});await e.batchSet([{id:"1",name:"Alice",age:30},{id:"2",name:"Bob",age:25}]);const t=[];for await(const r of e.search())t.push(r);expect(t).toHaveLength(2),await e.batchSet([{id:"1",name:"Alice2",age:31},{id:"2",name:"Bob2",age:26}]);const a=[];for await(const r of e.search())a.push(r);expect(a).toEqual([{id:"1",name:"Alice2",age:31},{id:"2",name:"Bob2",age:26}])}),it("should deleteBy condition",async()=>{const e=i({backend:c,tableName:"State3",key:"id"});await e.batchSet([{id:"1",name:"Alice",age:30},{id:"2",name:"Bob",age:25},{id:"3",name:"Carol",age:40}]);const t=await e.deleteBy({age:{gt:30}});expect(t.length).toBe(1);const a=[];for await(const r of e.search())a.push(r);expect(a.map(r=>r.id)).toEqual(["1","2"])}),it("should get by key and with selector",async()=>{const e=i({backend:c,tableName:"State4",key:"id"});await e.set({id:"1",name:"Alice",age:30});const t=await e.get("1");expect(t).toEqual({id:"1",name:"Alice",age:30});const a=await e.get("1",o=>o.name);expect(a).toBe("Alice");const r=await e.get("999");expect(r).toBeUndefined()}),it("should count documents with and without where",async()=>{const e=i({backend:c,tableName:"State5",key:"id"});await e.batchSet([{id:"1",name:"Alice",age:30},{id:"2",name:"Bob",age:25},{id:"3",name:"Carol",age:40}]),expect(await e.count()).toBe(3),expect(await e.count({where:{age:{gt:30}}})).toBe(1)}),it("should support search with options",async()=>{const e=i({backend:c,tableName:"State6",key:"id"});await e.batchSet([{id:"1",name:"Alice",age:30},{id:"2",name:"Bob",age:25},{id:"3",name:"Carol",age:40}]);const t=[];for await(const a of e.search({where:{age:{lt:35}}}))t.push(a);expect(t.map(a=>a.id)).toEqual(["1","2"])})}),describe("groupBy",()=>{it("should group by a simple field and count",async()=>{const e=i({backend:c,tableName:"GroupBy1",key:"id"});await e.batchSet([{id:"1",name:"Apple",category:"fruit",price:1},{id:"2",name:"Banana",category:"fruit",price:2},{id:"3",name:"Carrot",category:"vegetable",price:1},{id:"4",name:"Orange",category:"fruit",price:3},{id:"5",name:"Broccoli",category:"vegetable",price:2}]);const t=await e.groupBy("category");expect(t).toHaveLength(2);const a=t.find(o=>o.key==="fruit"),r=t.find(o=>o.key==="vegetable");expect(a?.count).toBe(3),expect(r?.count).toBe(2)}),it("should group by with where clause filter",async()=>{const e=i({backend:c,tableName:"GroupBy2",key:"id"});await e.batchSet([{id:"1",name:"Apple",category:"fruit",price:1},{id:"2",name:"Banana",category:"fruit",price:5},{id:"3",name:"Carrot",category:"vegetable",price:1},{id:"4",name:"Orange",category:"fruit",price:3},{id:"5",name:"Broccoli",category:"vegetable",price:6}]);const t=await e.groupBy("category",{where:{price:{gt:2}}});expect(t).toHaveLength(2);const a=t.find(o=>o.key==="fruit"),r=t.find(o=>o.key==="vegetable");expect(a?.count).toBe(2),expect(r?.count).toBe(1)}),it("should group by numeric field",async()=>{const e=i({backend:c,tableName:"GroupBy3",key:"id"});await e.batchSet([{id:"1",name:"Apple",category:"fruit",price:1},{id:"2",name:"Banana",category:"fruit",price:2},{id:"3",name:"Carrot",category:"vegetable",price:1},{id:"4",name:"Orange",category:"fruit",price:1}]);const t=await e.groupBy("price");expect(t).toHaveLength(2);const a=t.find(o=>o.key===1),r=t.find(o=>o.key===2);expect(a?.count).toBe(3),expect(r?.count).toBe(1)}),it("should return empty array for empty table",async()=>{const t=await i({backend:c,tableName:"GroupBy4",key:"id"}).groupBy("category");expect(t).toEqual([])}),it("should handle null/undefined values in grouped field",async()=>{const e=i({backend:c,tableName:"GroupBy5",key:"id"});await e.batchSet([{id:"1",name:"A",tag:"red"},{id:"2",name:"B",tag:"blue"},{id:"3",name:"C"},{id:"4",name:"D",tag:"red"}]);const t=await e.groupBy("tag");expect(t.length).toBeGreaterThanOrEqual(2);const a=t.find(o=>o.key==="red"),r=t.find(o=>o.key==="blue");expect(a?.count).toBe(2),expect(r?.count).toBe(1)}),it("should verify count matches sum of grouped counts",async()=>{const e=i({backend:c,tableName:"GroupBy6",key:"id"});await e.batchSet([{id:"1",name:"Apple",category:"fruit",price:1},{id:"2",name:"Banana",category:"fruit",price:2},{id:"3",name:"Carrot",category:"vegetable",price:1},{id:"4",name:"Orange",category:"fruit",price:3},{id:"5",name:"Broccoli",category:"vegetable",price:2}]);const t=await e.count(),r=(await e.groupBy("category")).reduce((o,n)=>o+n.count,0);expect(t).toBe(5),expect(r).toBe(t)}),it("should verify count with where matches grouped count with same where",async()=>{const e=i({backend:c,tableName:"GroupBy7",key:"id"});await e.batchSet([{id:"1",name:"Apple",category:"fruit",price:1},{id:"2",name:"Banana",category:"fruit",price:5},{id:"3",name:"Carrot",category:"vegetable",price:1},{id:"4",name:"Orange",category:"fruit",price:3},{id:"5",name:"Broccoli",category:"vegetable",price:6}]);const t={price:{gt:2}},a=await e.count({where:t}),o=(await e.groupBy("category",{where:t})).reduce((n,s)=>n+s.count,0);expect(a).toBe(3),expect(o).toBe(a)}),it("should have proper TypeScript inference for key type",async()=>{const e=i({backend:c,tableName:"GroupBy8",key:"id"});await e.batchSet([{id:"1",name:"Apple",category:"fruit",price:1},{id:"2",name:"Banana",category:"fruit",price:2}]);const a=(await e.groupBy("category"))[0].key;expect(typeof a).toBe("string");const o=(await e.groupBy("price"))[0].key;expect(typeof o).toBe("number")}),it("should infer nested field types correctly",async()=>{const e=i({backend:c,tableName:"GroupBy9",key:"id"});await e.batchSet([{id:"1",details:{category:"A",info:{rating:5}}},{id:"2",details:{category:"A",info:{rating:3}}},{id:"3",details:{category:"B",info:{rating:4}}}]);const t=await e.groupBy("details.category"),a=t[0].key;expect(typeof a).toBe("string"),expect(t).toHaveLength(2);const r=await e.groupBy("details.info.rating"),o=r[0].key;expect(typeof o).toBe("number"),expect(r).toHaveLength(3)})});
@@ -1 +0,0 @@
1
- import{MapDeque as t}from"../table/map-deque";describe("MapDeque",()=>{it("should throw if maxSize <= 0",()=>{expect(()=>new t(0)).toThrow(RangeError),expect(()=>new t(-1)).toThrow(RangeError)}),it("should add items up to maxSize",()=>{const e=new t(2);e.set("a",1),e.set("b",2),expect(e.size).toBe(2),expect(e.get("a")).toBe(1),expect(e.get("b")).toBe(2)}),it("should evict the oldest item when maxSize is exceeded",()=>{const e=new t(2);e.set("a",1),e.set("b",2),e.set("c",3),expect(e.size).toBe(2),expect(e.has("a")).toBe(!1),expect(e.get("b")).toBe(2),expect(e.get("c")).toBe(3)}),it("should update value if key already exists and not evict",()=>{const e=new t(2);e.set("a",1),e.set("b",2),e.set("a",42),expect(e.size).toBe(2),expect(e.get("a")).toBe(42),expect(e.get("b")).toBe(2)}),it("should work with initial entries",()=>{const e=[["x",10],["y",20]],s=new t(3,e);expect(s.size).toBe(2),expect(s.get("x")).toBe(10),expect(s.get("y")).toBe(20)}),it("should evict in insertion order, not key order",()=>{const e=new t(2);e.set("b",1),e.set("a",2),e.set("c",3),expect(e.size).toBe(2),expect(e.has("b")).toBe(!1),expect(e.has("a")).toBe(!0),expect(e.has("c")).toBe(!0)})});
@@ -1 +0,0 @@
1
- import{bunMemoryBackend as l}from"../table/bun-backend";import{createTable as c}from"../table/table";describe("table",()=>{let i=l(),t,r;beforeEach(async()=>{i=l(),t=await c({backend:i,tableName:"TestTable",key:"name"}),r=await c({backend:i,tableName:"TestTableNested",key:"info.name",indexes:["info.age","info.city"]})}),it("should set and get items",async()=>{const e=await t.set({name:"Alice",age:30,city:"Paris"});expect(e.key).toBe("Alice"),expect(e.op).toBe("insert");const o=await t.get("Alice");expect(o).toEqual({name:"Alice",age:30,city:"Paris"});const a=await t.set({name:"Alice",age:31,city:"Paris"});expect(a.key).toBe("Alice"),expect(a.op).toBe("update");const n=await t.get("Alice");expect(n).toEqual({name:"Alice",age:31,city:"Paris"})}),it("should set and get nested key",async()=>{const e=await r.set({info:{name:"Bob",age:25,city:"London"}});expect(e.key).toBe("Bob"),expect(e.op).toBe("insert");const o=await r.get("Bob");expect(o).toEqual({info:{name:"Bob",age:25,city:"London"}});const a=await r.set({info:{name:"Bob",age:26,city:"London"}});expect(a.key).toBe("Bob"),expect(a.op).toBe("update");const n=await r.get("Bob");expect(n).toEqual({info:{name:"Bob",age:26,city:"London"}});const s=[];for await(const d of r.search({where:{info:{city:{like:"London"}}}}))s.push(d);expect(s.length).toBe(1)}),it("should count items and count with where",async()=>{await t.set({name:"Alice",age:30,city:"Paris"}),await t.set({name:"Bob",age:25,city:"London"}),expect(await t.count()).toBe(2),expect(await t.count({where:{city:"Paris"}})).toBe(1)}),it("should search with ordering, limit and offset",async()=>{const e=[{name:"Alice",age:30,city:"Paris"},{name:"Bob",age:25,city:"London"},{name:"Carol",age:35,city:"Berlin"}];for(const s of e)await t.set(s);const o=[];for await(const s of t.search({sortBy:"age",order:"asc"}))o.push(s);expect(o.map(s=>s.name)).toEqual(["Bob","Alice","Carol"]);const a=[];for await(const s of t.search({sortBy:"age",order:"asc",limit:2}))a.push(s);expect(a.map(s=>s.name)).toEqual(["Bob","Alice"]);const n=[];for await(const s of t.search({sortBy:"age",order:"asc",offset:1,limit:2}))n.push(s);expect(n.map(s=>s.name)).toEqual(["Alice","Carol"])}),it("should deleteBy where clause",async()=>{await t.set({name:"Dave",age:40,city:"NY"}),await t.set({name:"Eve",age:45,city:"NY"}),await t.set({name:"Frank",age:50,city:"LA"}),expect(await t.count()).toBe(3),await t.deleteBy({city:"NY"}),expect(await t.count()).toBe(1),expect(await t.get("Frank")).toEqual({name:"Frank",age:50,city:"LA"}),expect(await t.get("Dave")).toBeUndefined()}),it("should use selector in get and search",async()=>{await t.set({name:"Gary",age:60,city:"SF"});const e=await t.get("Gary",({age:a})=>a);expect(e).toBe(60);const o=[];for await(const a of t.search({select:({city:n})=>n}))o.push(a);expect(o).toEqual(["SF"])}),it("should delete items by key",async()=>{await t.set({name:"Helen",age:28,city:"Rome"}),expect(await t.get("Helen")).toBeDefined(),await t.delete("Helen"),expect(await t.get("Helen")).toBeUndefined()}),it("should test search with 1000 items",async()=>{const e=[];for(let a=0;a<1e3;a++)e.push({name:`Person${a}`,age:Math.floor(Math.random()*100),city:"City"+a%10});for(const a of e)await t.set(a);const o=[];for await(const a of t.search({sortBy:"age",order:"asc",limit:100}))o.push(a);expect(o.length).toBe(100)}),it("should handle operations on an empty table",async()=>{expect(await t.count()).toBe(0),expect(await t.get("NonExistent")).toBeUndefined();const e=[];for await(const o of t.search({sortBy:"age",order:"asc"}))e.push(o);expect(e.length).toBe(0)}),it("should handle duplicate keys gracefully",async()=>{await t.set({name:"Alice",age:30,city:"Paris"}),await t.set({name:"Alice",age:35,city:"Berlin"});const e=await t.get("Alice");expect(e).toEqual({name:"Alice",age:35,city:"Berlin"})}),it("should handle edge cases in selectors",async()=>{await t.set({name:"Charlie",age:40,city:"NY"});const e=await t.get("Charlie",()=>null);expect(e).toBeNull();const o=await t.get("Charlie",()=>{});expect(o).toBeUndefined()}),it("should clear the table",async()=>{await t.set({name:"Alice",age:30,city:"Paris"}),await t.set({name:"Bob",age:25,city:"London"}),expect(await t.count()).toBe(2),await t.clear(),expect(await t.count()).toBe(0)}),it("should use fts index",async()=>{const e=await c({backend:i,tableName:"TestTableFTS",key:"id",indexes:["fts:content"]});await e.set({id:"1",content:"The \u010Coho brown fox"}),await e.set({id:"2",content:"jumps over the lazy dog"}),await e.set({id:"3",content:"hello world"});const o=[];for await(const n of e.search({where:{content:{fts:["coho","fox"]}}}))o.push(n);expect(o.length).toBe(1),expect(o[0].id).toBe("1");const a=[];for await(const n of e.search({where:{content:{fts:["the"]}}}))a.push(n);expect(a.length).toBe(2)}),it("should use fts index with custom tokenizer options",async()=>{const e=await c({backend:i,tableName:"TestTableFTS2",key:"id",indexes:[{type:"fts",path:"content",tokenizer:{removeDiacritics:0,tokenChars:"abc",separators:"xyz"}}]});await e.set({id:"1",content:"abc xyz"}),await e.set({id:"2",content:"abc"}),await e.set({id:"3",content:"other"});const o=[];for await(const n of e.search({where:{content:{fts:["abc"]}}}))o.push(n);expect(o.length).toBe(2);const a=[];for await(const n of e.search({where:{content:{fts:["xyz"]}}}))a.push(n);expect(a.length).toBe(1),expect(a[0].id).toBe("1")}),it("should support multiple fts fields",async()=>{const e=await c({backend:i,tableName:"TestTableFTSMulti",key:"id",indexes:[{type:"fts",path:"title"},{type:"fts",path:"body"}]});await e.set({id:"1",title:"Hello",body:"World"}),await e.set({id:"2",title:"Foo",body:"Bar"}),await e.set({id:"3",title:"Hello",body:"Bar"});const o=[];for await(const n of e.search({where:{title:{fts:["Hello"]}}}))o.push(n);expect(o.length).toBe(2);const a=[];for await(const n of e.search({where:{body:{fts:["Bar"]}}}))a.push(n);expect(a.length).toBe(2)}),it("should handle fts search with no results",async()=>{const e=await c({backend:i,tableName:"TestTableFTSNone",key:"id",indexes:["fts:content"]});await e.set({id:"1",content:"foo bar"});const o=[];for await(const a of e.search({where:{content:{fts:["notfound"]}}}))o.push(a);expect(o.length).toBe(0)}),it("should custom fn fts index",async()=>{const e=await c({backend:i,tableName:"TestTableFTS",key:"id",indexes:[{type:"fts",path:"content",tokenizer:{removeDiacritics:1}}]});await e.set({id:"1",content:"The \u010Coho brown fox"}),await e.set({id:"2",content:"jumps over the lazy dog"}),await e.set({id:"3",content:"hello world"});const o=[];for await(const n of e.search({where:{content:{fts:["coho","fox"]}}}))o.push(n);expect(o.length).toBe(1),expect(o[0].id).toBe("1");const a=[];for await(const n of e.search({where:{content:{fts:["the"]}}}))a.push(n);expect(a.length).toBe(2)}),it("should test fts index with nested fields",async()=>{const e=await c({backend:i,tableName:"TestTableFTSNested",key:"id",indexes:["fts:info.content"]});await e.set({id:"1",info:{content:"The quick brown fox"}}),await e.set({id:"2",info:{content:"jumps over the lazy dog"}}),await e.set({id:"3",info:{content:"hello world"}});const o=[];for await(const n of e.search({where:{info:{content:{fts:["quick","fox"]}}}}))o.push(n);expect(o.length).toBe(1),expect(o[0].id).toBe("1");const a=[];for await(const n of e.search({where:{info:{content:{fts:["the"]}}}}))a.push(n);expect(a.length).toBe(2)})});
@@ -1 +0,0 @@
1
- import{unicodeTokenizer as t}from"../table/tokenizer";describe("tokenizer",()=>{const o=[{options:{},expected:'"unicode61"'},{options:{removeDiacritics:1},expected:'"unicode61", "remove_diacritics=1"'},{options:{tokenChars:"abc"},expected:`"unicode61", "tokenchars='abc'"`},{options:{separators:"xyz"},expected:`"unicode61", "separators='xyz'"`},{options:{removeDiacritics:2,tokenChars:"a-b",separators:"x,y"},expected:`"unicode61", "remove_diacritics=2", "tokenchars='a-b'", "separators='x,y'"`},{options:{tokenChars:"a'b",separators:"c'd"},expected:`"unicode61", "tokenchars='a''b'", "separators='c''d'"`},{options:{removeDiacritics:0,tokenChars:"",separators:""},expected:'"unicode61", "remove_diacritics=0"'},{options:{removeDiacritics:1,tokenChars:"abc",separators:"xyz"},expected:`"unicode61", "remove_diacritics=1", "tokenchars='abc'", "separators='xyz'"`}];for(const e of o)it(`returns expected tokenizer string for options: ${JSON.stringify(e.options)}`,()=>{expect(t(e.options)).toBe(e.expected)})});
@@ -1 +0,0 @@
1
- import{createTable as n}from"../table";import{bunMemoryBackend as c}from"../table/bun-backend";describe("where clauses",()=>{const a=c();it("should handle where where array of conditions",async()=>{const e=await n({backend:a,tableName:"TestTableNestedOptional",key:"id",indexes:["content"]});await e.set({id:"1",content:"The quick brown fox"}),await e.set({id:"2",content:"The jumps over the lazy dog"}),await e.set({id:"3"});const t=[];for await(const i of e.search({where:{content:{like:["The%"]}}}))t.push(i);expect(t.length).toBe(2),expect(t[0].id).toBe("1")}),it("should create nested index for optional nested fields",async()=>{const e=await n({backend:a,tableName:"TestTableNestedOptional",key:"id",indexes:["fts:info.content"]});await e.set({id:"1",info:{content:"The quick brown fox"}}),await e.set({id:"2",info:{content:"jumps over the lazy dog"}}),await e.set({id:"3"});const t=[];for await(const s of e.search({where:{info:{content:{like:["The%"]}}}}))t.push(s);expect(t.length).toBe(1),expect(t[0].id).toBe("1");const i=[];for await(const s of e.search({where:{OR:[{info:{content:{like:["The%"]}}},{info:{content:{like:["jumps%"]}}}]}}))i.push(s);expect(i.length).toBe(2);const o=[];for await(const s of e.search({where:{info:{content:"nonexistent"}}}))o.push(s);expect(o.length).toBe(0)}),it("should handle FTS queries",async()=>{const e=await n({backend:a,tableName:"TestTableFts",key:"id",indexes:["fts:content"]});await e.set({id:"1",content:"The quick brown fox"}),await e.set({id:"2",content:"Jumps over the lazy dog"}),await e.set({id:"3",content:"Another document"});const t=[];for await(const i of e.search({where:{content:{fts:"quick"}}}))t.push(i);expect(t.length).toBe(1),expect(t[0].id).toBe("1")}),it("should handle nested where conditions",async()=>{const e=await n({backend:a,tableName:"TestTableNested",key:"id",indexes:["info.content"]});await e.set({id:"1",info:{content:"Nested quick brown fox"}}),await e.set({id:"2",info:{content:"Nested jumps over the lazy dog"}});const t=[];for await(const i of e.search({where:{info:{content:{like:"Nested%"}}}}))t.push(i);expect(t.length).toBe(2)}),it("should handle complex operators",async()=>{const e=await n({backend:a,tableName:"TestTableComplex",key:"id",indexes:["value"]});await e.set({id:"1",value:10}),await e.set({id:"2",value:20}),await e.set({id:"3",value:30});const t=[];for await(const i of e.search({where:{value:{gt:15,lt:25}},sortBy:"value"}))t.push(i);expect(t.length).toBe(1),expect(t[0].id).toBe("2")}),it("should handle NOT conditions",async()=>{const e=await n({backend:a,tableName:"TestTableNot",key:"id",indexes:["value"]});await e.set({id:"1",value:"apple"}),await e.set({id:"2",value:"banana"}),await e.set({id:"3",value:"cherry"});const t=[];for await(const i of e.search({where:{NOT:{value:"banana"}}}))t.push(i);expect(t.length).toBe(2),expect(t.map(i=>i.value)).toEqual(["apple","cherry"])}),it("should handle AND conditions",async()=>{const e=await n({backend:a,tableName:"TestTableAnd",key:"id",indexes:["category","price"]});await e.set({id:"1",category:"fruit",price:10}),await e.set({id:"2",category:"fruit",price:20}),await e.set({id:"3",category:"vegetable",price:15});const t=[];for await(const i of e.search({where:{AND:[{category:"fruit"},{price:{lt:15}}]}}))t.push(i);expect(t.length).toBe(1),expect(t[0].id).toBe("1")}),it("should handle OR conditions",async()=>{const e=await n({backend:a,tableName:"TestTableOr",key:"id",indexes:["type"]});await e.set({id:"1",type:"A"}),await e.set({id:"2",type:"B"}),await e.set({id:"3",type:"C"});const t=[];for await(const i of e.search({where:{OR:[{type:"A"},{type:"C"}]}}))t.push(i);expect(t.length).toBe(2),expect(t.map(i=>i.type)).toEqual(["A","C"])}),it("should handle nested AND/OR/NOT conditions",async()=>{const e=await n({backend:a,tableName:"TestTableNestedLogic",key:"id",indexes:["category","price"]});await e.set({id:"1",category:"fruit",price:10}),await e.set({id:"2",category:"fruit",price:20}),await e.set({id:"3",category:"fruit",price:15});const t={AND:[{category:{is:"fruit"}},{OR:[{price:{lt:15}},{price:{is:15}}]}]},i=[];for await(const s of e.search({}))i.push(s);expect(i.length).toBe(3);const o=[];for await(const s of e.search({where:t}))o.push(s);expect(o.length).toBe(2)})});
@@ -1 +0,0 @@
1
- import{STATE_SCHEDULER as u}from"../create";import{getId as m}from"../utils/id";import{createTable as d}from"./table/table";function h(l){let s;async function o(){if(!s){const{backend:e,...n}=l,t=e instanceof Promise?await e:e;s=await d({backend:t,...n})}return s}const i=m();u.add(i,{onScheduleDone(e){if(!e)return;const n=e,t={};for(const c of n)c.removedAll&&(t.removedAll=!0),c.mutations&&(t.mutations||(t.mutations=[]),t.mutations.push(...c.mutations));for(const c of r)c(t)}});function a(e){u.schedule(i,e)}const r=new Set;return{subscribe(e){return r.add(e),()=>r.delete(e)},async clear(){const e=await o();return a({removedAll:!0}),e.clear()},async set(e){const t=await(await o()).set(e);return a({mutations:[t]}),t},async batchSet(e){const t=await(await o()).batchSet(e);return a({mutations:t}),t},async batchDelete(e){const t=await(await o()).batchDelete(e);return a({mutations:t}),t},async delete(e){const t=await(await o()).delete(e);return t&&a({mutations:[t]}),t},async deleteBy(e){const t=await(await o()).deleteBy(e);return a({mutations:t}),t},async get(e,n){return(await o()).get(e,n)},async*search(e={}){const n=await o();for await(const t of n.search(e))yield t},async count(e){return await(await o()).count(e)},async groupBy(e,n){return await(await o()).groupBy(e,n)}}}export{h as createSqliteState};
@@ -1 +0,0 @@
1
- export*from"./create-sqlite";export*from"./table";export*from"./use-sqlite-count";export*from"./use-sqlite";
@@ -1 +0,0 @@
1
- const e=":memory:";export{e as IN_MEMORY_DB};
@@ -1 +0,0 @@
1
- import{Database as m}from"bun:sqlite";import{MapDeque as p}from"./map-deque";function d(){const n=m.open(":memory:"),r=new p(100);function s(e){if(r.has(e))return r.get(e);const t=n.prepare(e);return r.set(e,t),t}const c={execute:async(e,t=[])=>{const a=s(e).run(...t);return{rowsAffected:a.changes,changes:a.changes}},transaction:async e=>n.transaction(()=>e(c))(),path:n.filename,select:async(e,t=[])=>s(e).all(...t)};return c}export{d as bunMemoryBackend};
@@ -1 +0,0 @@
1
- export*from"./backend";export*from"./table.types";export*from"./where";export*from"./table";export*from"./map-deque";export*from"./tokenizer";
@@ -1 +0,0 @@
1
- class a extends Map{constructor(e,t){super(t);this.maxSize=e;if(this.maxSize<=0)throw new RangeError("maxSize must be greater than 0")}set(e,t){if(this.has(e))return super.set(e,t),this;if(this.size>=this.maxSize){const s=this.keys().next().value;s!==void 0&&this.delete(s)}return super.set(e,t),this}}export{a as MapDeque};
@@ -1,43 +0,0 @@
1
- import{unicodeTokenizer as _}from"./tokenizer";import{getWhereQuery as h}from"./where";const F=500,C=100;function p(E){return"$."+E}function M(E,s){if(!(!E||!s))return s.split(".").reduce((t,w)=>{if(typeof t=="object"&&t!==null&&w in t)return t[w]},E)}async function B(E){const{backend:s,tableName:t,indexes:w,key:$,disablePragmaOptimization:x}=E,d=$!==void 0;x||(await s.execute("PRAGMA journal_mode=WAL;"),await s.execute("PRAGMA synchronous=NORMAL;"),await s.execute("PRAGMA temp_store=MEMORY;"),await s.execute("PRAGMA cache_size=-20000;")),d?await s.execute(`
2
- CREATE TABLE IF NOT EXISTS ${t} (
3
- key TEXT PRIMARY KEY,
4
- data TEXT NOT NULL
5
- );
6
- `):await s.execute(`
7
- CREATE TABLE IF NOT EXISTS ${t} (
8
- data TEXT NOT NULL
9
- );
10
- `);let l;const y=[],f={};for(const e of w??[])if(typeof e=="string"&&e.startsWith("fts:")){const n=e.slice(4),o=n.replaceAll(".","_");y.push(n),f[n]=o}else if(typeof e=="object"&&e.type==="fts"){const n=e.path,o=n.replaceAll(".","_");if(y.push(n),f[n]=o,e.tokenizer){if(!l)l=e.tokenizer;else if(l!==e.tokenizer)throw new Error(`Conflicting FTS tokenizers: already using "${l}", got "${e.tokenizer}"`)}}else{const n=String(e);await s.execute(`CREATE INDEX IF NOT EXISTS idx_${t}_${n.replaceAll(/\W/g,"_")}
11
- ON ${t} (json_extract(data, '${p(n)}'));`)}if(y.length>0){let e;typeof l=="object"?e=_(l):l===void 0?e='"unicode61", "remove_diacritics=1"':e=l;const n=y.map(r=>f[r]).join(", "),o=`
12
- CREATE VIRTUAL TABLE IF NOT EXISTS ${t}_fts
13
- USING fts5(${n}, tokenize=${e});
14
- `;await s.execute(o),await s.execute(`
15
- CREATE TRIGGER IF NOT EXISTS ${t}_ai
16
- AFTER INSERT ON ${t}
17
- BEGIN
18
- INSERT INTO ${t}_fts(rowid, ${n})
19
- VALUES (
20
- new.rowid,
21
- ${y.map(r=>`json_extract(new.data, '${p(r)}')`).join(", ")}
22
- );
23
- END;
24
- `),await s.execute(`
25
- CREATE TRIGGER IF NOT EXISTS ${t}_ad
26
- AFTER DELETE ON ${t}
27
- BEGIN
28
- DELETE FROM ${t}_fts WHERE rowid = old.rowid;
29
- END;
30
- `),await s.execute(`
31
- CREATE TRIGGER IF NOT EXISTS ${t}_au
32
- AFTER UPDATE ON ${t}
33
- BEGIN
34
- UPDATE ${t}_fts
35
- SET ${y.map(r=>`${f[r]}=json_extract(new.data, '${p(r)}')`).join(", ")}
36
- WHERE rowid = old.rowid;
37
- END;
38
- `)}function A(e){if(d)return M(e,String($))}const O={backend:s,async set(e,n){const o=n??s,r=JSON.stringify(e);if(d){const a=A(e);if(a==null)throw new Error(`Document is missing the configured key "${String($)}".`);return(await o.select(`SELECT key FROM ${t} WHERE key = ?`,[a])).length>0?(await o.execute(`UPDATE ${t} SET data = ? WHERE key = ?`,[r,a]),{key:a,op:"update",document:e}):(await o.execute(`INSERT INTO ${t} (key, data) VALUES (?, ?)`,[a,r]),{key:a,op:"insert",document:e})}await o.execute(`INSERT INTO ${t} (data) VALUES (?)`,[r]);const u=(await o.select("SELECT last_insert_rowid() AS id"))[0]?.id;if(typeof u!="number")throw new Error("Failed to retrieve last_insert_rowid()");return{key:u,op:"insert",document:e}},async get(e,n=o=>o){const o=d?"key = ?":"rowid = ?",r=await s.select(`SELECT rowid, data FROM ${t} WHERE ${o}`,[e]);if(r.length===0)return;const{data:i,rowid:u}=r[0],a=JSON.parse(i),c=d?A(a)??u:u;return n(a,{rowId:u,key:c})},async delete(e,n){const o=n??s,r=d?"key = ?":"rowid = ?";if(await o.execute(`DELETE FROM ${t} WHERE ${r}`,[e]),((await s.select("SELECT changes() AS c"))[0]?.c??0)>0)return{key:e,op:"delete"}},async*search(e={}){const{sortBy:n,order:o="asc",limit:r,offset:i=0,where:u,select:a=T=>T,pageSize:c=C}=e,m=h(u,t),g=`SELECT rowid, data FROM ${t} ${m}`;let S=0,k=i;for(;;){let T=g;n?T+=` ORDER BY json_extract(data, '${p(String(n))}') COLLATE NOCASE ${o.toUpperCase()}`:T+=d?` ORDER BY key COLLATE NOCASE ${o.toUpperCase()}`:` ORDER BY rowid ${o.toUpperCase()}`;const N=r?Math.min(c,r-S):c;T+=` LIMIT ${N} OFFSET ${k}`;const R=await s.select(T);if(R.length===0)break;for(const{rowid:D,data:L}of R){if(r&&S>=r)return;const I=JSON.parse(L),b=d?A(I)??D:D;yield a(I,{rowId:D,key:b}),S++}if(R.length<N||r&&S>=r)break;k+=R.length}},async count(e={}){const n=h(e.where,t),o=`SELECT COUNT(*) as count FROM ${t} ${n}`;return(await s.select(o))[0]?.count??0},async deleteBy(e){const n=h(e,t),o=d?"key":"rowid",r=[];return await s.transaction(async i=>{const u=await i.select(`SELECT ${o} AS k FROM ${t} ${n}`);if(u.length===0)return;const a=u.map(c=>c.k);for(let c=0;c<a.length;c+=F){const m=a.slice(c,c+F),g=m.map(()=>"?").join(",");await i.execute(`DELETE FROM ${t} WHERE ${o} IN (${g})`,m)}for(const c of a)r.push({key:c,op:"delete",document:void 0})}),r},async clear(){await s.execute(`DELETE FROM ${t}`)},async groupBy(e,n={}){const o=h(n.where,t),i=`
39
- SELECT json_extract(data, '${p(String(e))}') AS groupKey, COUNT(*) AS count
40
- FROM ${t}
41
- ${o}
42
- GROUP BY groupKey
43
- `;return(await s.select(i)).map(a=>({key:a.groupKey,count:a.count}))},async batchSet(e){const n=[];return await s.transaction(async o=>{for(const r of e){const i=await O.set(r,o);n.push(i)}}),n},async batchDelete(e){const n=[];return await s.transaction(async o=>{for(const r of e){const i=await O.delete(r,o);i&&n.push(i)}}),n}};return O}export{C as DEFAULT_PAGE_SIZE,B as createTable,M as getByPath,p as toJsonPath};
File without changes
@@ -1 +0,0 @@
1
- function o(i={}){const{removeDiacritics:t,tokenChars:r,separators:n}=i,e=[];return t!==void 0&&e.push(`"remove_diacritics=${t}"`),r&&r.length>0&&e.push(`"tokenchars='${r.replaceAll("'","''")}'"`),n&&n.length>0&&e.push(`"separators='${n.replaceAll("'","''")}'"`),e.length===0||!(e.length>0)?'"unicode61"':`"unicode61", ${e.join(", ")}`}export{o as unicodeTokenizer};
@@ -1 +0,0 @@
1
- function $(n){return typeof n=="string"?`'${n.replaceAll("'","''")}'`:typeof n=="number"?n.toString():typeof n=="boolean"?n?"1":"0":`'${String(n).replaceAll("'","''")}'`}function A(n,r,t){const o=t?`${t}.`:"";return n==="KEY"?`"${o}key"`:typeof r=="string"?`CAST(json_extract(${o}data, '$.${n}') AS TEXT)`:typeof r=="number"?`CAST(json_extract(${o}data, '$.${n}') AS NUMERIC)`:typeof r=="boolean"?`CAST(json_extract(${o}data, '$.${n}') AS INTEGER)`:`json_extract(${o}data, '$.${n}')`}const p=new Set(["is","isNot","gt","gte","lt","lte","in","notIn","like","fts"]);function R(n,r=""){const t={};for(const[o,c]of Object.entries(n)){if(o==="AND"||o==="OR"||o==="NOT"){t[o]=c;continue}const a=r?`${r}.${o}`:o;c&&typeof c=="object"&&!Array.isArray(c)&&!Object.keys(c).some(i=>p.has(i))?Object.assign(t,R(c,a)):t[a]=c}return t}function T(n,r,t){if(!n||typeof n!="object")return"";if(n.AND){const i=Array.isArray(n.AND)?n.AND.map(u=>T(u,r,t)).filter(Boolean):[];return i.length>0?`(${i.join(" AND ")})`:""}if(n.OR){const i=Array.isArray(n.OR)?n.OR.map(u=>T(u,r,t)).filter(Boolean):[];return i.length>0?`(${i.join(" OR ")})`:""}if(n.NOT){const i=T(n.NOT,r,t);return i?`(NOT ${i})`:""}const o=R(n);let c="",a=!1;for(const[i,u]of Object.entries(o)){if(u==null)continue;let d;typeof u!="object"||Array.isArray(u)?d=Array.isArray(u)?{in:u}:{is:u}:d=u;for(const s of Object.keys(d)){const l=d[s];if(l==null)continue;const y=Array.isArray(l)?l:[l];if(y.length!==0){if(s==="fts"){if(!t)throw new Error("FTS requires tableName for JOIN reference");const e=y.map(f=>`EXISTS (SELECT 1 FROM ${t}_fts f WHERE f.rowid = ${r??t}.rowid AND ${t}_fts MATCH ${$(f)})`).join(" AND ");c+=(a?" AND ":"")+e,a=!0;continue}if(s==="is"||s==="isNot"||s==="in"||s==="notIn"){const e=A(i,y[0],r),f=y.map($).join(","),g=s==="is"?y.length>1?`${e} IN (${f})`:`${e} = ${$(y[0])}`:s==="isNot"?y.length>1?`${e} NOT IN (${f})`:`${e} <> ${$(y[0])}`:s==="in"?`${e} IN (${f})`:`${e} NOT IN (${f})`;c+=(a?" AND ":"")+g,a=!0;continue}for(const e of y){const f=A(i,e,r),g=s==="gt"?`${f} > ${$(e)}`:s==="gte"?`${f} >= ${$(e)}`:s==="lt"?`${f} < ${$(e)}`:s==="lte"?`${f} <= ${$(e)}`:`${f} LIKE ${$(e)}`;c+=(a?" AND ":"")+g,a=!0}}}}return a?`(${c})`:""}function k(n,r){if(!n)return"";const t=T(n,void 0,r);return t?`WHERE ${t}`:""}export{T as getWhere,k as getWhereQuery};
@@ -1 +0,0 @@
1
- import{useCallback as l,useEffect as b,useLayoutEffect as y,useReducer as d,useRef as D}from"react";function w(t,f={},r=[]){const n=D(0),[,o]=d(e=>e+1,0),u=l(async()=>{const e=await t.count(f);n.current=e,o()},r);return b(()=>{u()},r),y(()=>{const e=t.subscribe(a=>{const{mutations:c,removedAll:m}=a;if(m){n.current=0,o();return}if(!c)return;let s=!1;for(const p of c){const{op:i}=p;if(i==="insert"||i==="delete"){s=!0;break}}s&&u()});return()=>{e()}},[t]),n.current}export{w as useSqliteCount};
@@ -1 +0,0 @@
1
- import{useCallback as h,useLayoutEffect as O,useReducer as U,useRef as L,useState as M}from"react";import{DEFAULT_PAGE_SIZE as N}from"./table";import{shallow as z}from"../utils/shallow";const E=1e4;function j(s,y){if(s.length!==y.length)return!1;for(const[o,l]of s.entries())if(!Object.is(l,y[o]))return!1;return!0}function Z(s,y={},o=[]){const{select:l,pageSize:R=N}=y,e=L(null),[,A]=U(n=>n+1,0),t=L(new Map),w=L(null),[q,k]=M(null),_=q===null||!j(q,o),v=h(()=>{const{select:n,...d}=y;w.current=s.search({select:(i,f)=>({doc:i,meta:f}),...d})},[s,...o]),p=h(()=>{e.current=[],t.current.clear(),v()},[v]),S=h(async n=>{e.current===null&&(e.current=[]),n===!0&&p();const{current:d}=w;if(!d)return!0;let i=!1;for(let f=0;f<R;f++){const u=await d.next();if(u.done){w.current=null,i=!0;break}t.current.has(u.value.meta.key)||(e.current.push(l?l(u.value.doc):u.value.doc),t.current.set(u.value.meta.key,e.current.length-1))}return e.current=[...e.current],i},[]),D=h(async()=>{const n=await S(!1);return A(),n},[S]);O(()=>{const n=s.subscribe(async d=>{const{mutations:i,removedAll:f}=d;if(f&&p(),!i)return;const u=e.current?.length??0;let I=u,b=!1;const x=new Set;for(const a of i){const{key:r,op:g,document:m}=a;switch(g){case"insert":{I+=1;break}case"delete":{if(e.current&&e.current.length>0&&t.current.has(r)){const c=t.current.get(r);if(c===void 0)break;x.add(c),b=!0}break}case"update":{if(t.current.has(r)){const c=t.current.get(r);if(c!==void 0&&e.current){const T=l?l(m):m,K=e.current[c];z(K,T)||(e.current[c]=T,e.current=[...e.current],b=!0)}}else{const c=await s.get(r,l);c&&(e.current=[...e.current??[],c],t.current.set(r,e.current.length-1),b=!0)}break}}}if(x.size>0&&e.current&&e.current.length>0){const a=new Map;e.current=e.current?.filter((g,m)=>!x.has(m));let r=0;for(const[g,m]of t.current)x.has(m)||(a.set(g,r),r++);t.current=a}const P=u!==I;if(P||b){if(P){await S(!0);let a=0;for(;(e.current?.length??0)<I&&a<E;)await S(!1),a++;a===E&&console.warn("Reached maximum iterations in fillNextPage loop. Possible duplicate or data issue.")}A()}});return()=>{n()}},[s]),O(()=>{const n=o;p(),D().then(()=>{k(n)})},o);const C=h(async()=>{k(null),p(),await D(),k(o)},[D,p,o]);return[e.current,{nextPage:D,reset:C,keysIndex:t.current,isStale:_}]}export{Z as useSqliteValue};
@@ -1 +0,0 @@
1
- import{create as r}from"../../create";import{AbortError as B}from"../common";import{isPromise as o,isFunction as s,isSetValueFunction as u,isMap as n,isSet as i,isArray as a,isEqualBase as f,isUndefined as l,isState as t,isAbortError as c}from"../is";describe("isPromise",()=>{it("should return true for a Promise",()=>{expect(o(Promise.resolve())).toBe(!0)}),it("should return false for a non-Promise",()=>{expect(o(123)).toBe(!1)})}),describe("isFunction",()=>{it("should return true for a function",()=>{expect(s(()=>{})).toBe(!0)}),it("should return false for a non-function",()=>{expect(s(123)).toBe(!1)})}),describe("isSetValueFunction",()=>{it("should return true for a function",()=>{expect(u(()=>{})).toBe(!0)}),it("should return false for a non-function",()=>{expect(u(123)).toBe(!1)})}),describe("isMap",()=>{it("should return true for a Map",()=>{expect(n(new Map)).toBe(!0)}),it("should return false for a non-Map",()=>{expect(n(123)).toBe(!1)})}),describe("isSet",()=>{it("should return true for a Set",()=>{expect(i(new Set)).toBe(!0)}),it("should return false for a non-Set",()=>{expect(i(123)).toBe(!1)})}),describe("isArray",()=>{it("should return true for an array",()=>{expect(a([])).toBe(!0)}),it("should return false for a non-array",()=>{expect(a(123)).toBe(!1)})}),describe("isEqualBase",()=>{it("should return true for equal values",()=>{expect(f(1,1)).toBe(!0)}),it("should return false for non-equal values",()=>{expect(f(1,2)).toBe(!1)})}),describe("isUndefined",()=>{it("should return true for undefined",()=>{expect(l(void 0)).toBe(!0)}),it("should return false for a non-undefined",()=>{expect(l(123)).toBe(!1)})}),describe("isState",()=>{it("should return true for a State real",()=>{const e=r(1);expect(t(e)).toBe(!0)}),it("should return true for a State with derived",()=>{const d=r(1).select(p=>p);expect(t(d)).toBe(!1)}),it("should return false for a non-State",()=>{expect(t(123)).toBe(!1)})}),describe("isAbortError",()=>{it("should return true for an AbortError",()=>{const e=new B;expect(c(e)).toBe(!0)}),it("should return false for a non-AbortError",()=>{const e=new Error("asd");expect(c(e)).toBe(!1)})});
@@ -1 +0,0 @@
1
- import{shallow as t}from"../shallow";describe("shallow",()=>{it("should return true for identical primitive values",()=>{expect(t(1,1)).toBe(!0),expect(t("a","a")).toBe(!0),expect(t(!0,!0)).toBe(!0)}),it("should return false for different primitive values",()=>{expect(t(1,2)).toBe(!1),expect(t("a","b")).toBe(!1),expect(t(!0,!1)).toBe(!1)}),it("should return true for identical objects",()=>{const e={a:1};expect(t(e,e)).toBe(!0)}),it("should return false for different objects with diff properties",()=>{expect(t({a:1},{a:2})).toBe(!1)}),it("should return true for identical arrays",()=>{const e=[1,2,3];expect(t(e,e)).toBe(!0)}),it("should return true for different arrays with same elements",()=>{expect(t([1,2,3],[1,2,3])).toBe(!0)}),it("should return true for identical Maps",()=>{const e=new Map([["a",1]]);expect(t(e,e)).toBe(!0)}),it("should return true for different Maps with same entries",()=>{expect(t(new Map([["a",1]]),new Map([["a",1]]))).toBe(!0)}),it("should return true for identical Sets",()=>{const e=new Set([1,2,3]);expect(t(e,e)).toBe(!0)}),it("should return true for different Sets with same elements",()=>{expect(t(new Set([1,2,3]),new Set([1,2,3]))).toBe(!0)}),it("should return true for objects with same reference",()=>{const e={a:1};expect(t(e,e)).toBe(!0)}),it("should return true for objects with different references",()=>{expect(t({a:1},{a:1})).toBe(!0)}),it("should return true for arrays with same reference",()=>{const e=[1,2,3];expect(t(e,e)).toBe(!0)}),it("should return true for arrays with different references",()=>{expect(t([1,2,3],[1,2,3])).toBe(!0)}),it("should return true for Maps with same reference",()=>{const e=new Map([["a",1]]);expect(t(e,e)).toBe(!0)}),it("should return true for Maps with different references",()=>{expect(t(new Map([["a",1]]),new Map([["a",1]]))).toBe(!0)}),it("should return true for Sets with same reference",()=>{const e=new Set([1,2,3]);expect(t(e,e)).toBe(!0)}),it("should return true for Sets with different references",()=>{expect(t(new Set([1,2,3]),new Set([1,2,3]))).toBe(!0)}),it("should return true for objects with same keys and values",()=>{const e={a:1,b:2},r={a:1,b:2};expect(t(e,r)).toBe(!0)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return true for arrays with same elements",()=>{const e=[1,2,3],r=[1,2,3];expect(t(e,r)).toBe(!0)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return true for Maps with same entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",2]]);expect(t(e,r)).toBe(!0)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return true for Sets with same elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,3]);expect(t(e,r)).toBe(!0)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for different objects with same properties",()=>{expect(t({a:1},{a:2})).toBe(!1)}),it("should return false for different arrays with same elements",()=>{expect(t([1,2,3],[1,2,4])).toBe(!1)}),it("should return false for different Maps with same entries",()=>{expect(t(new Map([["a",1]]),new Map([["a",2]]))).toBe(!1)}),it("should return false for different Sets with same elements",()=>{expect(t(new Set([1,2,3]),new Set([1,2,4]))).toBe(!1)}),it("should return false for objects with different reference",()=>{expect(t({a:1},{a:2})).toBe(!1)}),it("should return false for arrays with different reference",()=>{expect(t([1,2,3],[1,2,4])).toBe(!1)}),it("should return false for Maps with different reference",()=>{expect(t(new Map([["a",1]]),new Map([["a",2]]))).toBe(!1)}),it("should return false for Sets with different reference",()=>{expect(t(new Set([1,2,3]),new Set([1,2,4]))).toBe(!1)}),it("should return false for objects with different keys or values in",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for objects with different keys or values",()=>{const e={a:1,b:2},r={a:1,b:3};expect(t(e,r)).toBe(!1)}),it("should return false for arrays with different elements",()=>{const e=[1,2,3],r=[1,2,4];expect(t(e,r)).toBe(!1)}),it("should return false for Maps with different entries",()=>{const e=new Map([["a",1],["b",2]]),r=new Map([["a",1],["b",3]]);expect(t(e,r)).toBe(!1)}),it("should return false for Sets with different elements",()=>{const e=new Set([1,2,3]),r=new Set([1,2,4]);expect(t(e,r)).toBe(!1)}),it("should return false for null and non-null values",()=>{expect(t(null,{})).toBe(!1),expect(t({},null)).toBe(!1)}),it("should return false for objects with different number of keys",()=>{expect(t({a:1},{a:1,b:2})).toBe(!1)}),it("should return false for objects with different keys",()=>{expect(t({a:1},{b:1})).toBe(!1)}),it("should return false for objects with different values",()=>{expect(t({a:1},{a:2})).toBe(!1)}),it("should return false for arrays with different lengths",()=>{expect(t([1,2],[1,2,3])).toBe(!1)}),it("should return false for arrays with different elements",()=>{expect(t([1,2,3],[1,2,4])).toBe(!1)}),it("should return false for Maps with different sizes",()=>{expect(t(new Map([["a",1]]),new Map([["a",1],["b",2]]))).toBe(!1)}),it("should return false for Maps with different keys",()=>{expect(t(new Map([["a",1]]),new Map([["b",1]]))).toBe(!1)}),it("should return false for Maps with different values",()=>{expect(t(new Map([["a",1]]),new Map([["a",2]]))).toBe(!1)}),it("should return false for Sets with different sizes",()=>{expect(t(new Set([1,2]),new Set([1,2,3]))).toBe(!1)}),it("should return false for Sets with different elements",()=>{expect(t(new Set([1,2,3]),new Set([1,2,4]))).toBe(!1)}),it("should return true compare simple values",()=>{expect(t(1,1)).toBe(!0),expect(t("a","a")).toBe(!0),expect(t(!0,!0)).toBe(!0)})});
@@ -1,264 +0,0 @@
1
- import { createSqliteState } from '../create-sqlite'
2
- import { bunMemoryBackend } from '../table/bun-backend'
3
-
4
- const backend = bunMemoryBackend()
5
- interface Person {
6
- id: string
7
- name: string
8
- age: number
9
- }
10
-
11
- describe('create-sqlite-state', () => {
12
- it('should batchSet and update multiple documents', async () => {
13
- const sql = createSqliteState<Person>({ backend, tableName: 'State2', key: 'id' })
14
- await sql.batchSet([
15
- { id: '1', name: 'Alice', age: 30 },
16
- { id: '2', name: 'Bob', age: 25 },
17
- ])
18
- const all = []
19
- for await (const p of sql.search()) all.push(p)
20
- expect(all).toHaveLength(2)
21
- // update both
22
- await sql.batchSet([
23
- { id: '1', name: 'Alice2', age: 31 },
24
- { id: '2', name: 'Bob2', age: 26 },
25
- ])
26
- const updated = []
27
- for await (const p of sql.search()) updated.push(p)
28
- expect(updated).toEqual([
29
- { id: '1', name: 'Alice2', age: 31 },
30
- { id: '2', name: 'Bob2', age: 26 },
31
- ])
32
- })
33
-
34
- it('should deleteBy condition', async () => {
35
- const sql = createSqliteState<Person>({ backend, tableName: 'State3', key: 'id' })
36
- await sql.batchSet([
37
- { id: '1', name: 'Alice', age: 30 },
38
- { id: '2', name: 'Bob', age: 25 },
39
- { id: '3', name: 'Carol', age: 40 },
40
- ])
41
- const deleted = await sql.deleteBy({ age: { gt: 30 } })
42
- expect(deleted.length).toBe(1)
43
- const all = []
44
- for await (const p of sql.search()) all.push(p)
45
- expect(all.map((p) => p.id)).toEqual(['1', '2'])
46
- })
47
-
48
- it('should get by key and with selector', async () => {
49
- const sql = createSqliteState<Person>({ backend, tableName: 'State4', key: 'id' })
50
- await sql.set({ id: '1', name: 'Alice', age: 30 })
51
- const doc = await sql.get('1')
52
- expect(doc).toEqual({ id: '1', name: 'Alice', age: 30 })
53
- const name = await sql.get('1', (d) => d.name)
54
- expect(name).toBe('Alice')
55
- const missing = await sql.get('999')
56
- expect(missing).toBeUndefined()
57
- })
58
-
59
- it('should count documents with and without where', async () => {
60
- const sql = createSqliteState<Person>({ backend, tableName: 'State5', key: 'id' })
61
- await sql.batchSet([
62
- { id: '1', name: 'Alice', age: 30 },
63
- { id: '2', name: 'Bob', age: 25 },
64
- { id: '3', name: 'Carol', age: 40 },
65
- ])
66
- expect(await sql.count()).toBe(3)
67
- expect(await sql.count({ where: { age: { gt: 30 } } })).toBe(1)
68
- })
69
-
70
- it('should support search with options', async () => {
71
- const sql = createSqliteState<Person>({ backend, tableName: 'State6', key: 'id' })
72
- await sql.batchSet([
73
- { id: '1', name: 'Alice', age: 30 },
74
- { id: '2', name: 'Bob', age: 25 },
75
- { id: '3', name: 'Carol', age: 40 },
76
- ])
77
- const results = []
78
- for await (const p of sql.search({ where: { age: { lt: 35 } } })) results.push(p)
79
- expect(results.map((p) => p.id)).toEqual(['1', '2'])
80
- })
81
- })
82
-
83
- interface Product {
84
- id: string
85
- name: string
86
- category: string
87
- price: number
88
- }
89
-
90
- describe('groupBy', () => {
91
- it('should group by a simple field and count', async () => {
92
- const sql = createSqliteState<Product>({ backend, tableName: 'GroupBy1', key: 'id' })
93
- await sql.batchSet([
94
- { id: '1', name: 'Apple', category: 'fruit', price: 1 },
95
- { id: '2', name: 'Banana', category: 'fruit', price: 2 },
96
- { id: '3', name: 'Carrot', category: 'vegetable', price: 1 },
97
- { id: '4', name: 'Orange', category: 'fruit', price: 3 },
98
- { id: '5', name: 'Broccoli', category: 'vegetable', price: 2 },
99
- ])
100
-
101
- const grouped = await sql.groupBy('category')
102
-
103
- expect(grouped).toHaveLength(2)
104
- const fruitGroup = grouped.find((g) => g.key === 'fruit')
105
- const vegetableGroup = grouped.find((g) => g.key === 'vegetable')
106
- expect(fruitGroup?.count).toBe(3)
107
- expect(vegetableGroup?.count).toBe(2)
108
- })
109
-
110
- it('should group by with where clause filter', async () => {
111
- const sql = createSqliteState<Product>({ backend, tableName: 'GroupBy2', key: 'id' })
112
- await sql.batchSet([
113
- { id: '1', name: 'Apple', category: 'fruit', price: 1 },
114
- { id: '2', name: 'Banana', category: 'fruit', price: 5 },
115
- { id: '3', name: 'Carrot', category: 'vegetable', price: 1 },
116
- { id: '4', name: 'Orange', category: 'fruit', price: 3 },
117
- { id: '5', name: 'Broccoli', category: 'vegetable', price: 6 },
118
- ])
119
-
120
- // Only group items with price > 2
121
- const grouped = await sql.groupBy('category', { where: { price: { gt: 2 } } })
122
-
123
- expect(grouped).toHaveLength(2)
124
- const fruitGroup = grouped.find((g) => g.key === 'fruit')
125
- const vegetableGroup = grouped.find((g) => g.key === 'vegetable')
126
- expect(fruitGroup?.count).toBe(2) // Banana (5), Orange (3)
127
- expect(vegetableGroup?.count).toBe(1) // Broccoli (6)
128
- })
129
-
130
- it('should group by numeric field', async () => {
131
- const sql = createSqliteState<Product>({ backend, tableName: 'GroupBy3', key: 'id' })
132
- await sql.batchSet([
133
- { id: '1', name: 'Apple', category: 'fruit', price: 1 },
134
- { id: '2', name: 'Banana', category: 'fruit', price: 2 },
135
- { id: '3', name: 'Carrot', category: 'vegetable', price: 1 },
136
- { id: '4', name: 'Orange', category: 'fruit', price: 1 },
137
- ])
138
-
139
- const grouped = await sql.groupBy('price')
140
-
141
- expect(grouped).toHaveLength(2)
142
- const price1 = grouped.find((g) => g.key === 1)
143
- const price2 = grouped.find((g) => g.key === 2)
144
- expect(price1?.count).toBe(3)
145
- expect(price2?.count).toBe(1)
146
- })
147
-
148
- it('should return empty array for empty table', async () => {
149
- const sql = createSqliteState<Product>({ backend, tableName: 'GroupBy4', key: 'id' })
150
-
151
- const grouped = await sql.groupBy('category')
152
-
153
- expect(grouped).toEqual([])
154
- })
155
-
156
- it('should handle null/undefined values in grouped field', async () => {
157
- interface ItemWithOptional {
158
- id: string
159
- name: string
160
- tag?: string
161
- }
162
- const sql = createSqliteState<ItemWithOptional>({ backend, tableName: 'GroupBy5', key: 'id' })
163
- await sql.batchSet([
164
- { id: '1', name: 'A', tag: 'red' },
165
- { id: '2', name: 'B', tag: 'blue' },
166
- { id: '3', name: 'C' }, // no tag
167
- { id: '4', name: 'D', tag: 'red' },
168
- ])
169
-
170
- const grouped = await sql.groupBy('tag')
171
-
172
- // Should have 3 groups: red, blue, and null/undefined
173
- expect(grouped.length).toBeGreaterThanOrEqual(2)
174
- const redGroup = grouped.find((g) => g.key === 'red')
175
- const blueGroup = grouped.find((g) => g.key === 'blue')
176
- expect(redGroup?.count).toBe(2)
177
- expect(blueGroup?.count).toBe(1)
178
- })
179
-
180
- it('should verify count matches sum of grouped counts', async () => {
181
- const sql = createSqliteState<Product>({ backend, tableName: 'GroupBy6', key: 'id' })
182
- await sql.batchSet([
183
- { id: '1', name: 'Apple', category: 'fruit', price: 1 },
184
- { id: '2', name: 'Banana', category: 'fruit', price: 2 },
185
- { id: '3', name: 'Carrot', category: 'vegetable', price: 1 },
186
- { id: '4', name: 'Orange', category: 'fruit', price: 3 },
187
- { id: '5', name: 'Broccoli', category: 'vegetable', price: 2 },
188
- ])
189
-
190
- const totalCount = await sql.count()
191
- const grouped = await sql.groupBy('category')
192
- const sumOfCounts = grouped.reduce((sum, group) => sum + group.count, 0)
193
-
194
- expect(totalCount).toBe(5)
195
- expect(sumOfCounts).toBe(totalCount)
196
- })
197
-
198
- it('should verify count with where matches grouped count with same where', async () => {
199
- const sql = createSqliteState<Product>({ backend, tableName: 'GroupBy7', key: 'id' })
200
- await sql.batchSet([
201
- { id: '1', name: 'Apple', category: 'fruit', price: 1 },
202
- { id: '2', name: 'Banana', category: 'fruit', price: 5 },
203
- { id: '3', name: 'Carrot', category: 'vegetable', price: 1 },
204
- { id: '4', name: 'Orange', category: 'fruit', price: 3 },
205
- { id: '5', name: 'Broccoli', category: 'vegetable', price: 6 },
206
- ])
207
-
208
- const whereClause = { price: { gt: 2 } }
209
- const filteredCount = await sql.count({ where: whereClause })
210
- const grouped = await sql.groupBy('category', { where: whereClause })
211
- const sumOfCounts = grouped.reduce((sum, group) => sum + group.count, 0)
212
-
213
- expect(filteredCount).toBe(3) // Banana (5), Orange (3), Broccoli (6)
214
- expect(sumOfCounts).toBe(filteredCount)
215
- })
216
-
217
- it('should have proper TypeScript inference for key type', async () => {
218
- const sql = createSqliteState<Product>({ backend, tableName: 'GroupBy8', key: 'id' })
219
- await sql.batchSet([
220
- { id: '1', name: 'Apple', category: 'fruit', price: 1 },
221
- { id: '2', name: 'Banana', category: 'fruit', price: 2 },
222
- ])
223
-
224
- // Group by string field - key should be string
225
- const categoryGroups = await sql.groupBy('category')
226
- const categoryKey: string = categoryGroups[0].key // TypeScript should infer string
227
- expect(typeof categoryKey).toBe('string')
228
-
229
- // Group by number field - key should be number
230
- const priceGroups = await sql.groupBy('price')
231
- const priceKey: number = priceGroups[0].key // TypeScript should infer number
232
- expect(typeof priceKey).toBe('number')
233
- })
234
-
235
- it('should infer nested field types correctly', async () => {
236
- interface NestedProduct {
237
- id: string
238
- details: {
239
- category: string
240
- info: {
241
- rating: number
242
- }
243
- }
244
- }
245
- const sql = createSqliteState<NestedProduct>({ backend, tableName: 'GroupBy9', key: 'id' })
246
- await sql.batchSet([
247
- { id: '1', details: { category: 'A', info: { rating: 5 } } },
248
- { id: '2', details: { category: 'A', info: { rating: 3 } } },
249
- { id: '3', details: { category: 'B', info: { rating: 4 } } },
250
- ])
251
-
252
- // Group by nested string field
253
- const categoryGroups = await sql.groupBy('details.category')
254
- const nestedKey: string = categoryGroups[0].key
255
- expect(typeof nestedKey).toBe('string')
256
- expect(categoryGroups).toHaveLength(2)
257
-
258
- // Group by deeply nested number field
259
- const ratingGroups = await sql.groupBy('details.info.rating')
260
- const ratingKey: number = ratingGroups[0].key
261
- expect(typeof ratingKey).toBe('number')
262
- expect(ratingGroups).toHaveLength(3)
263
- })
264
- })