muya 2.5.4 → 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
@@ -1,234 +0,0 @@
1
- import { createTable } from '../table'
2
- import { bunMemoryBackend } from '../table/bun-backend'
3
- import { type Where } from '../table/where'
4
-
5
- describe('where clauses', () => {
6
- const backend = bunMemoryBackend()
7
-
8
- it('should handle where where array of conditions', async () => {
9
- const tableNestedOptional = await createTable<{ id: string; content?: string }>({
10
- backend,
11
- tableName: 'TestTableNestedOptional',
12
- key: 'id',
13
- indexes: ['content'],
14
- })
15
-
16
- await tableNestedOptional.set({ id: '1', content: 'The quick brown fox' })
17
- await tableNestedOptional.set({ id: '2', content: 'The jumps over the lazy dog' })
18
- await tableNestedOptional.set({ id: '3' }) // No `content` field
19
-
20
- const results: { id: string; content?: string }[] = []
21
- for await (const doc of tableNestedOptional.search({
22
- where: { content: { like: ['The%'] } },
23
- })) {
24
- results.push(doc)
25
- }
26
- expect(results.length).toBe(2)
27
- expect(results[0].id).toBe('1')
28
- })
29
- it('should create nested index for optional nested fields', async () => {
30
- type TestDoc = { id: string; info?: { content?: string } }
31
- const tableNestedOptional = await createTable<TestDoc>({
32
- backend,
33
- tableName: 'TestTableNestedOptional',
34
- key: 'id',
35
- indexes: ['fts:info.content'],
36
- })
37
-
38
- await tableNestedOptional.set({ id: '1', info: { content: 'The quick brown fox' } })
39
- await tableNestedOptional.set({ id: '2', info: { content: 'jumps over the lazy dog' } })
40
- await tableNestedOptional.set({ id: '3' }) // No `info` field
41
-
42
- const results: TestDoc[] = []
43
- for await (const doc of tableNestedOptional.search({
44
- where: { info: { content: { like: ['The%'] } } },
45
- })) {
46
- results.push(doc)
47
- }
48
- expect(results.length).toBe(1)
49
- expect(results[0].id).toBe('1')
50
-
51
- const results2: TestDoc[] = []
52
- for await (const doc of tableNestedOptional.search({
53
- where: { OR: [{ info: { content: { like: ['The%'] } } }, { info: { content: { like: ['jumps%'] } } }] },
54
- })) {
55
- results2.push(doc)
56
- }
57
- expect(results2.length).toBe(2)
58
-
59
- const results3: TestDoc[] = []
60
- for await (const doc of tableNestedOptional.search({
61
- where: { info: { content: 'nonexistent' } },
62
- })) {
63
- results3.push(doc)
64
- }
65
- expect(results3.length).toBe(0)
66
- })
67
- it('should handle FTS queries', async () => {
68
- const tableFts = await createTable<{ id: string; content: string }>({
69
- backend,
70
- tableName: 'TestTableFts',
71
- key: 'id',
72
- indexes: ['fts:content'],
73
- })
74
-
75
- await tableFts.set({ id: '1', content: 'The quick brown fox' })
76
- await tableFts.set({ id: '2', content: 'Jumps over the lazy dog' })
77
- await tableFts.set({ id: '3', content: 'Another document' })
78
-
79
- const results: { id: string; content: string }[] = []
80
- for await (const doc of tableFts.search({
81
- where: { content: { fts: 'quick' } },
82
- })) {
83
- results.push(doc)
84
- }
85
- expect(results.length).toBe(1)
86
- expect(results[0].id).toBe('1')
87
- })
88
-
89
- it('should handle nested where conditions', async () => {
90
- const tableNested = await createTable<{ id: string; info: { content: string } }>({
91
- backend,
92
- tableName: 'TestTableNested',
93
- key: 'id',
94
- indexes: ['info.content'],
95
- })
96
-
97
- await tableNested.set({ id: '1', info: { content: 'Nested quick brown fox' } })
98
- await tableNested.set({ id: '2', info: { content: 'Nested jumps over the lazy dog' } })
99
-
100
- const results: { id: string; info: { content: string } }[] = []
101
- for await (const doc of tableNested.search({
102
- where: { info: { content: { like: 'Nested%' } } },
103
- })) {
104
- results.push(doc)
105
- }
106
- expect(results.length).toBe(2)
107
- })
108
-
109
- it('should handle complex operators', async () => {
110
- const tableComplex = await createTable<{ id: string; value: number }>({
111
- backend,
112
- tableName: 'TestTableComplex',
113
- key: 'id',
114
- indexes: ['value'],
115
- })
116
-
117
- await tableComplex.set({ id: '1', value: 10 })
118
- await tableComplex.set({ id: '2', value: 20 })
119
- await tableComplex.set({ id: '3', value: 30 })
120
-
121
- const results: { id: string; value: number }[] = []
122
- for await (const doc of tableComplex.search({
123
- where: { value: { gt: 15, lt: 25 } },
124
- sortBy: 'value',
125
- })) {
126
- results.push(doc)
127
- }
128
- expect(results.length).toBe(1)
129
- expect(results[0].id).toBe('2')
130
- })
131
-
132
- it('should handle NOT conditions', async () => {
133
- const tableNot = await createTable<{ id: string; value: string }>({
134
- backend,
135
- tableName: 'TestTableNot',
136
- key: 'id',
137
- indexes: ['value'],
138
- })
139
-
140
- await tableNot.set({ id: '1', value: 'apple' })
141
- await tableNot.set({ id: '2', value: 'banana' })
142
- await tableNot.set({ id: '3', value: 'cherry' })
143
-
144
- const results: { id: string; value: string }[] = []
145
- for await (const doc of tableNot.search({
146
- where: { NOT: { value: 'banana' } },
147
- })) {
148
- results.push(doc)
149
- }
150
- expect(results.length).toBe(2)
151
- expect(results.map((doc) => doc.value)).toEqual(['apple', 'cherry'])
152
- })
153
-
154
- it('should handle AND conditions', async () => {
155
- const tableAnd = await createTable<{ id: string; category: string; price: number }>({
156
- backend,
157
- tableName: 'TestTableAnd',
158
- key: 'id',
159
- indexes: ['category', 'price'],
160
- })
161
-
162
- await tableAnd.set({ id: '1', category: 'fruit', price: 10 })
163
- await tableAnd.set({ id: '2', category: 'fruit', price: 20 })
164
- await tableAnd.set({ id: '3', category: 'vegetable', price: 15 })
165
-
166
- const results: { id: string; category: string; price: number }[] = []
167
- for await (const doc of tableAnd.search({
168
- where: { AND: [{ category: 'fruit' }, { price: { lt: 15 } }] },
169
- })) {
170
- results.push(doc)
171
- }
172
- expect(results.length).toBe(1)
173
- expect(results[0].id).toBe('1')
174
- })
175
-
176
- it('should handle OR conditions', async () => {
177
- const tableOr = await createTable<{ id: string; type: string }>({
178
- backend,
179
- tableName: 'TestTableOr',
180
- key: 'id',
181
- indexes: ['type'],
182
- })
183
-
184
- await tableOr.set({ id: '1', type: 'A' })
185
- await tableOr.set({ id: '2', type: 'B' })
186
- await tableOr.set({ id: '3', type: 'C' })
187
-
188
- const results: { id: string; type: string }[] = []
189
- for await (const doc of tableOr.search({
190
- where: { OR: [{ type: 'A' }, { type: 'C' }] },
191
- })) {
192
- results.push(doc)
193
- }
194
- expect(results.length).toBe(2)
195
- expect(results.map((doc) => doc.type)).toEqual(['A', 'C'])
196
- })
197
-
198
- it('should handle nested AND/OR/NOT conditions', async () => {
199
- const tableNestedLogic = await createTable<{ id: string; category: string; price: number }>({
200
- backend,
201
- tableName: 'TestTableNestedLogic',
202
- key: 'id',
203
- indexes: ['category', 'price'],
204
- })
205
-
206
- await tableNestedLogic.set({ id: '1', category: 'fruit', price: 10 })
207
- await tableNestedLogic.set({ id: '2', category: 'fruit', price: 20 })
208
- await tableNestedLogic.set({ id: '3', category: 'fruit', price: 15 })
209
-
210
- const whereClause: Where<{ category: string; price: number }> = {
211
- AND: [
212
- { category: { is: 'fruit' } },
213
- {
214
- OR: [{ price: { lt: 15 } }, { price: { is: 15 } }],
215
- },
216
- ],
217
- }
218
-
219
- const allData: { id: string; category: string; price: number }[] = []
220
- for await (const doc of tableNestedLogic.search({})) {
221
- allData.push(doc)
222
- }
223
- expect(allData.length).toBe(3)
224
-
225
- const results: { id: string; category: string; price: number }[] = []
226
- for await (const doc of tableNestedLogic.search({
227
- where: whereClause,
228
- })) {
229
- results.push(doc)
230
- }
231
-
232
- expect(results.length).toBe(2)
233
- })
234
- })
@@ -1,164 +0,0 @@
1
- import { STATE_SCHEDULER } from '../create'
2
- import { getId } from '../utils/id'
3
- import type { Backend } from './table'
4
- import { createTable } from './table/table'
5
- import type {
6
- DbOptions,
7
- DocType,
8
- DotPath,
9
- GetFieldType,
10
- GroupByOptions,
11
- GroupByResult,
12
- Key,
13
- MutationResult,
14
- SearchOptions,
15
- Table,
16
- } from './table/table.types'
17
- import type { Where } from './table/where'
18
-
19
- export interface CreateSqliteOptions<Document extends DocType> extends Omit<DbOptions<Document>, 'backend'> {
20
- readonly backend: Backend | Promise<Backend>
21
- }
22
-
23
- export interface MutationItems<Doc> {
24
- mutations?: MutationResult<Doc>[]
25
- removedAll?: boolean
26
- }
27
-
28
- export interface SyncTable<Document extends DocType> {
29
- readonly subscribe: (listener: (mutation: MutationItems<Document>) => void) => () => void
30
- readonly set: (document: Document) => Promise<MutationResult<Document>>
31
- readonly batchSet: (documents: Document[]) => Promise<MutationResult<Document>[]>
32
- readonly batchDelete: (keys: Key[]) => Promise<MutationResult<Document>[]>
33
- readonly get: <Selected = Document>(key: Key, selector?: (document: Document) => Selected) => Promise<Selected | undefined>
34
-
35
- readonly delete: (key: Key) => Promise<MutationResult<Document> | undefined>
36
- readonly search: <Selected = Document>(options?: SearchOptions<Document, Selected>) => AsyncIterableIterator<Selected>
37
- readonly count: (options?: { where?: Where<Document> }) => Promise<number>
38
- readonly deleteBy: (where: Where<Document>) => Promise<MutationResult<Document>[]>
39
- readonly clear: () => Promise<void>
40
- readonly groupBy: <Field extends DotPath<Document>>(
41
- field: Field,
42
- options?: GroupByOptions<Document>,
43
- ) => Promise<Array<GroupByResult<GetFieldType<Document, Field>>>>
44
- }
45
-
46
- /**
47
- * Create a SyncTable that wraps a Table and provides reactive capabilities
48
- * @param options Options to create the SyncTable, including the backend and table name
49
- * @returns A SyncTable instance with methods to interact with the underlying Table and manage reactive searches
50
- */
51
- export function createSqliteState<Document extends DocType>(options: CreateSqliteOptions<Document>): SyncTable<Document> {
52
- let cachedTable: Table<Document> | undefined
53
- /**
54
- * Get or create the underlying table
55
- * @returns The Table instance
56
- */
57
- async function getTable() {
58
- if (!cachedTable) {
59
- const { backend, ...rest } = options
60
- const resolvedBackend = backend instanceof Promise ? await backend : backend
61
- cachedTable = await createTable<Document>({ backend: resolvedBackend, ...rest })
62
- }
63
- return cachedTable
64
- }
65
-
66
- const id = getId()
67
- STATE_SCHEDULER.add(id, {
68
- onScheduleDone(unknownItems) {
69
- if (!unknownItems) {
70
- return
71
- }
72
- const items = unknownItems as MutationItems<Document>[]
73
- const merged: MutationItems<Document> = {}
74
- for (const item of items) {
75
- if (item.removedAll) {
76
- merged.removedAll = true
77
- }
78
- if (item.mutations) {
79
- if (!merged.mutations) {
80
- merged.mutations = []
81
- }
82
- merged.mutations.push(...item.mutations)
83
- }
84
- }
85
- for (const listener of listeners) {
86
- listener(merged)
87
- }
88
- },
89
- })
90
-
91
- /**
92
- * Notify all subscribers of changes
93
- * @param item The mutation items to notify subscribers about
94
- */
95
- function handleChanges(item: MutationItems<Document>) {
96
- STATE_SCHEDULER.schedule(id, item)
97
- }
98
-
99
- const listeners = new Set<(mutation: MutationItems<Document>) => void>()
100
-
101
- const state: SyncTable<Document> = {
102
- subscribe(listener) {
103
- listeners.add(listener)
104
- return () => listeners.delete(listener)
105
- },
106
- async clear() {
107
- const table = await getTable()
108
- handleChanges({ removedAll: true })
109
- return table.clear()
110
- },
111
- async set(document) {
112
- const table = await getTable()
113
- const changes = await table.set(document)
114
- handleChanges({ mutations: [changes] })
115
- return changes
116
- },
117
- async batchSet(documents) {
118
- const table = await getTable()
119
- const changes = await table.batchSet(documents)
120
- handleChanges({ mutations: changes })
121
- return changes
122
- },
123
- async batchDelete(keys) {
124
- const table = await getTable()
125
- const changes = await table.batchDelete(keys)
126
- handleChanges({ mutations: changes })
127
- return changes
128
- },
129
- async delete(key) {
130
- const table = await getTable()
131
- const changes = await table.delete(key)
132
- if (changes) {
133
- handleChanges({ mutations: [changes] })
134
- }
135
- return changes
136
- },
137
- async deleteBy(where) {
138
- const table = await getTable()
139
- const changes = await table.deleteBy(where)
140
- handleChanges({ mutations: changes })
141
- return changes
142
- },
143
- async get(key, selector) {
144
- const table = await getTable()
145
- return table.get(key, selector)
146
- },
147
- async *search(searchOptions = {}) {
148
- const table = await getTable()
149
- for await (const item of table.search(searchOptions)) {
150
- yield item
151
- }
152
- },
153
- async count(countOptions) {
154
- const table = await getTable()
155
- return await table.count(countOptions)
156
- },
157
- async groupBy(field, groupByOptions) {
158
- const table = await getTable()
159
- return await table.groupBy(field, groupByOptions)
160
- },
161
- }
162
-
163
- return state
164
- }
@@ -1,4 +0,0 @@
1
- export * from './create-sqlite'
2
- export * from './table'
3
- export * from './use-sqlite-count'
4
- export * from './use-sqlite'
@@ -1,21 +0,0 @@
1
- export const IN_MEMORY_DB = ':memory:'
2
-
3
- export interface QueryResult {
4
- /** The number of rows affected by the query. */
5
- rowsAffected: number
6
- /**
7
- * The last inserted `id`.
8
- *
9
- * This value is not set for Postgres databases. If the
10
- * last inserted id is required on Postgres, the `select` function
11
- * must be used, with a `RETURNING` clause
12
- * (`INSERT INTO todos (title) VALUES ($1) RETURNING id`).
13
- */
14
- lastInsertId?: number
15
- }
16
- export interface Backend {
17
- execute: (query: string, bindValues?: unknown[]) => Promise<QueryResult>
18
- select: <T>(query: string, bindValues?: unknown[]) => Promise<T>
19
- transaction: (callback: (tx: Backend) => Promise<void>) => Promise<void>
20
- path: string
21
- }
@@ -1,47 +0,0 @@
1
- import { Database, type Statement } from 'bun:sqlite'
2
- import type { Backend } from './backend'
3
- import { MapDeque } from './map-deque'
4
-
5
- /**
6
- * Create an in-memory SQLite backend using Bun's SQLite implementation
7
- * @returns A Backend instance for in-memory SQLite operations
8
- */
9
- export function bunMemoryBackend(): Backend {
10
- const db = Database.open(':memory:')
11
- const prepares = new MapDeque<string, Statement>(100)
12
- /**
13
- * Get or prepare a SQLite statement, caching it for future use
14
- * @param query The SQL query string
15
- * @returns The prepared SQLite statement
16
- */
17
- function getStatement(query: string): Statement {
18
- if (prepares.has(query)) {
19
- return prepares.get(query)!
20
- }
21
- const stmt = db.prepare(query)
22
- prepares.set(query, stmt)
23
- return stmt
24
- }
25
-
26
- const backend: Backend = {
27
- execute: async (query, params = []) => {
28
- const q = getStatement(query)
29
- const result = q.run(...(params as never[]))
30
- return {
31
- rowsAffected: result.changes,
32
- changes: result.changes,
33
- }
34
- },
35
- transaction: async (callback) => {
36
- return db.transaction(() => callback(backend))()
37
- },
38
- path: db.filename,
39
- select: async (query, params = []) => {
40
- const q = getStatement(query)
41
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
- const result = q.all(...(params as never[])) as Array<Record<string, any>>
43
- return result as never
44
- },
45
- }
46
- return backend
47
- }
@@ -1,6 +0,0 @@
1
- export * from './backend'
2
- export * from './table.types'
3
- export * from './where'
4
- export * from './table'
5
- export * from './map-deque'
6
- export * from './tokenizer'
@@ -1,29 +0,0 @@
1
- export class MapDeque<K, V> extends Map<K, V> {
2
- constructor(
3
- private maxSize: number,
4
- entries?: ReadonlyArray<readonly [K, V]> | null,
5
- ) {
6
- super(entries)
7
- if (this.maxSize <= 0) {
8
- throw new RangeError('maxSize must be greater than 0')
9
- }
10
- }
11
-
12
- override set(key: K, value: V): this {
13
- if (this.has(key)) {
14
- super.set(key, value)
15
- return this
16
- }
17
-
18
- if (this.size >= this.maxSize) {
19
- const firstKey = this.keys().next().value
20
- if (firstKey !== undefined) {
21
- this.delete(firstKey)
22
- }
23
- }
24
-
25
- super.set(key, value)
26
-
27
- return this
28
- }
29
- }