zeed 1.4.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/dist/{args-FLoL3OKJ.d.cts → args-CEjib9V9.d.mts} +1 -1
  2. package/dist/{args-WC9q5kz2.d.mts → args-DEig-jw4.d.cts} +1 -1
  3. package/dist/{clipboard-BkUO-syY.d.mts → clipboard-BusqmLLY.d.cts} +1 -1
  4. package/dist/{clipboard-Cfpr331X.d.cts → clipboard-DcuuFRwa.d.mts} +1 -1
  5. package/dist/common/exec/index.d.cts +2 -2
  6. package/dist/common/exec/index.d.mts +2 -2
  7. package/dist/common/exec/promise.d.cts +1 -1
  8. package/dist/common/exec/promise.d.mts +1 -1
  9. package/dist/common/exec/throttle-debounce.d.cts +1 -1
  10. package/dist/common/exec/throttle-debounce.d.mts +1 -1
  11. package/dist/common/index.cjs +21 -0
  12. package/dist/common/index.d.cts +14 -11
  13. package/dist/common/index.d.mts +15 -12
  14. package/dist/common/index.mjs +4 -1
  15. package/dist/common/msg/rpc.cjs +8 -8
  16. package/dist/common/msg/rpc.cjs.map +1 -1
  17. package/dist/common/msg/rpc.mjs +8 -8
  18. package/dist/common/msg/rpc.mjs.map +1 -1
  19. package/dist/common/schema/export-json-schema.cjs +40 -31
  20. package/dist/common/schema/export-json-schema.cjs.map +1 -1
  21. package/dist/common/schema/export-json-schema.mjs +40 -31
  22. package/dist/common/schema/export-json-schema.mjs.map +1 -1
  23. package/dist/common/schema/index.cjs +21 -0
  24. package/dist/common/schema/index.d.cts +6 -3
  25. package/dist/common/schema/index.d.mts +7 -4
  26. package/dist/common/schema/index.mjs +4 -1
  27. package/dist/common/schema/sql/expr.cjs +128 -0
  28. package/dist/common/schema/sql/expr.cjs.map +1 -0
  29. package/dist/common/schema/sql/expr.d.cts +2 -0
  30. package/dist/common/schema/sql/expr.d.mts +2 -0
  31. package/dist/common/schema/sql/expr.mjs +115 -0
  32. package/dist/common/schema/sql/expr.mjs.map +1 -0
  33. package/dist/common/schema/sql/index.cjs +23 -0
  34. package/dist/common/schema/sql/index.d.cts +4 -0
  35. package/dist/common/schema/sql/index.d.mts +4 -0
  36. package/dist/common/schema/sql/index.mjs +5 -0
  37. package/dist/common/schema/sql/select.cjs +143 -0
  38. package/dist/common/schema/sql/select.cjs.map +1 -0
  39. package/dist/common/schema/sql/select.d.cts +2 -0
  40. package/dist/common/schema/sql/select.d.mts +2 -0
  41. package/dist/common/schema/sql/select.mjs +139 -0
  42. package/dist/common/schema/sql/select.mjs.map +1 -0
  43. package/dist/common/schema/sql/table.cjs +23 -0
  44. package/dist/common/schema/sql/table.cjs.map +1 -0
  45. package/dist/common/schema/sql/table.d.cts +2 -0
  46. package/dist/common/schema/sql/table.d.mts +2 -0
  47. package/dist/common/schema/sql/table.mjs +20 -0
  48. package/dist/common/schema/sql/table.mjs.map +1 -0
  49. package/dist/common/schema/type-test.d.cts +1 -1
  50. package/dist/common/schema/type-test.d.mts +1 -1
  51. package/dist/common/schema/utils.d.cts +1 -1
  52. package/dist/common/schema/utils.d.mts +1 -1
  53. package/dist/common/schema/z.d.mts +1 -1
  54. package/dist/common/storage/index.d.cts +1 -1
  55. package/dist/common/storage/index.d.mts +1 -1
  56. package/dist/common/storage/memstorage.d.cts +1 -1
  57. package/dist/common/storage/memstorage.d.mts +1 -1
  58. package/dist/common/test.d.cts +1 -1
  59. package/dist/common/test.d.mts +1 -1
  60. package/dist/common/time.d.cts +1 -1
  61. package/dist/common/time.d.mts +1 -1
  62. package/dist/common/timeout.d.cts +1 -1
  63. package/dist/common/timeout.d.mts +1 -1
  64. package/dist/common/utils.d.cts +1 -1
  65. package/dist/common/utils.d.mts +1 -1
  66. package/dist/common/uuid.d.cts +1 -1
  67. package/dist/common/uuid.d.mts +1 -1
  68. package/dist/{crypto-CyTV7Qce.d.cts → crypto-D68rVmvU.d.mts} +1 -1
  69. package/dist/{crypto-LT7EC5_d.d.mts → crypto-KzGHoCJE.d.cts} +1 -1
  70. package/dist/{env-B3vOiVY8.d.cts → env-BJXdwBKq.d.mts} +1 -1
  71. package/dist/{env-C3npYe8w.d.mts → env-HsOnA_yK.d.cts} +1 -1
  72. package/dist/expr-CCKrqOw1.d.mts +25 -0
  73. package/dist/expr-yYgSeBZ3.d.cts +25 -0
  74. package/dist/{files-CDNKX9VI.d.mts → files-4O-PxnAC.d.cts} +1 -1
  75. package/dist/{files-DdI9UZvg.d.cts → files-BlpxqSTT.d.mts} +1 -1
  76. package/dist/{files-async-1V0bu_ca.d.cts → files-async-DFLC-Nkd.d.cts} +1 -1
  77. package/dist/{files-async-cBMkRwsu.d.mts → files-async-DfuEEDjH.d.mts} +1 -1
  78. package/dist/{filestorage-CXQ9MzeW.d.cts → filestorage-BjeBZEAs.d.cts} +1 -1
  79. package/dist/{filestorage-YzM2z9sU.d.mts → filestorage-CmfztpWm.d.mts} +1 -1
  80. package/dist/{fs-DHJ9AqUk.d.cts → fs-D837bjRT.d.cts} +1 -1
  81. package/dist/{fs-DgjZdpuF.d.mts → fs-DlYLapik.d.mts} +1 -1
  82. package/dist/{glob-Bfs7ZS_i.d.mts → glob-5yW09dkR.d.mts} +1 -1
  83. package/dist/{glob-Bt150jOY.d.cts → glob-CZaZPqiy.d.cts} +1 -1
  84. package/dist/index.all.cjs +21 -0
  85. package/dist/index.all.d.cts +28 -25
  86. package/dist/index.all.d.mts +29 -26
  87. package/dist/index.all.mjs +4 -1
  88. package/dist/index.browser.cjs +21 -0
  89. package/dist/index.browser.d.cts +14 -11
  90. package/dist/index.browser.d.mts +15 -12
  91. package/dist/index.browser.mjs +4 -1
  92. package/dist/index.jsr.d.cts +4 -4
  93. package/dist/index.jsr.d.mts +4 -4
  94. package/dist/index.node.cjs +21 -0
  95. package/dist/index.node.d.cts +28 -25
  96. package/dist/index.node.d.mts +29 -26
  97. package/dist/index.node.mjs +4 -1
  98. package/dist/{log-file-bsTsc9KM.d.cts → log-file-DwEDms1F.d.cts} +2 -2
  99. package/dist/{log-file-DTuImomJ.d.mts → log-file-QV1unm3z.d.mts} +2 -2
  100. package/dist/{log-file-rotation-_YruAcNc.d.cts → log-file-rotation-BpZxXYlU.d.cts} +2 -2
  101. package/dist/{log-file-rotation-FBmtp_Uz.d.mts → log-file-rotation-DanrO_2y.d.mts} +2 -2
  102. package/dist/{log-node-DlrXl3QO.d.mts → log-node-BSn7RqAc.d.mts} +1 -1
  103. package/dist/{log-node-Dk948mHX.d.cts → log-node-D_fiJL6x.d.cts} +1 -1
  104. package/dist/{log-rotation-CkyjZbK5.d.mts → log-rotation-BdGakFya.d.cts} +1 -1
  105. package/dist/{log-rotation-_d7iRm9s.d.cts → log-rotation-Ce4e-8LN.d.mts} +1 -1
  106. package/dist/{log-util-2Ls76P-0.d.cts → log-util-C0U3zCjw.d.cts} +1 -1
  107. package/dist/{log-util-Da_d19f8.d.mts → log-util-Da_UCcmt.d.mts} +1 -1
  108. package/dist/{memstorage-D5A9FwiP.d.mts → memstorage-BhWXthO8.d.mts} +1 -1
  109. package/dist/{memstorage-BcjQLdaQ.d.cts → memstorage-tvlWDYgS.d.cts} +1 -1
  110. package/dist/node/args.d.cts +1 -1
  111. package/dist/node/args.d.mts +1 -1
  112. package/dist/node/clipboard.d.cts +1 -1
  113. package/dist/node/clipboard.d.mts +1 -1
  114. package/dist/node/crypto.d.cts +1 -1
  115. package/dist/node/crypto.d.mts +1 -1
  116. package/dist/node/env.d.cts +1 -1
  117. package/dist/node/env.d.mts +1 -1
  118. package/dist/node/files-async.d.cts +1 -1
  119. package/dist/node/files-async.d.mts +1 -1
  120. package/dist/node/files.d.cts +1 -1
  121. package/dist/node/files.d.mts +1 -1
  122. package/dist/node/filestorage.d.cts +1 -1
  123. package/dist/node/filestorage.d.mts +1 -1
  124. package/dist/node/fs.d.cts +1 -1
  125. package/dist/node/fs.d.mts +1 -1
  126. package/dist/node/glob.d.cts +1 -1
  127. package/dist/node/glob.d.mts +1 -1
  128. package/dist/node/index.d.cts +14 -14
  129. package/dist/node/index.d.mts +14 -14
  130. package/dist/node/log/index.d.cts +5 -5
  131. package/dist/node/log/index.d.mts +5 -5
  132. package/dist/node/log/log-file-rotation.d.cts +1 -1
  133. package/dist/node/log/log-file-rotation.d.mts +1 -1
  134. package/dist/node/log/log-file.d.cts +1 -1
  135. package/dist/node/log/log-file.d.mts +1 -1
  136. package/dist/node/log/log-node.cjs +4 -13
  137. package/dist/node/log/log-node.cjs.map +1 -1
  138. package/dist/node/log/log-node.d.cts +1 -1
  139. package/dist/node/log/log-node.d.mts +1 -1
  140. package/dist/node/log/log-node.mjs +4 -13
  141. package/dist/node/log/log-node.mjs.map +1 -1
  142. package/dist/node/log/log-rotation.d.cts +1 -1
  143. package/dist/node/log/log-rotation.d.mts +1 -1
  144. package/dist/node/log/log-util.d.cts +1 -1
  145. package/dist/node/log/log-util.d.mts +1 -1
  146. package/dist/{promise-DGgiRckN.d.cts → promise-CU_CENbU.d.cts} +1 -1
  147. package/dist/{promise-MH3xAy4S.d.mts → promise-CoWXgo4w.d.mts} +1 -1
  148. package/dist/select-DrciHdk_.d.cts +52 -0
  149. package/dist/select-F2KpP6mo.d.mts +52 -0
  150. package/dist/table-Cr8tjDIL.d.mts +19 -0
  151. package/dist/table-IkLXirT-.d.cts +19 -0
  152. package/dist/{test-CAhm15f4.d.mts → test-DcXa0MeX.d.cts} +1 -1
  153. package/dist/{test-D2plOVHF.d.cts → test-jZsc7P2c.d.mts} +1 -1
  154. package/dist/{throttle-debounce-BLFxAZ8W.d.mts → throttle-debounce-CCh0F100.d.mts} +1 -1
  155. package/dist/{throttle-debounce-Psb0ay1r.d.cts → throttle-debounce-DyFiyoAk.d.cts} +1 -1
  156. package/dist/{time-BfKJBbym.d.cts → time-BgFZe9ys.d.cts} +1 -1
  157. package/dist/{time-DxE-vjjw.d.mts → time-DSV_k3mG.d.mts} +1 -1
  158. package/dist/{timeout-CnUk6Ruj.d.mts → timeout-DDSSNZY8.d.mts} +1 -1
  159. package/dist/{timeout-CpFcK8MD.d.cts → timeout-E3ZQbJgK.d.cts} +1 -1
  160. package/dist/{type-test-BiKyEZkc.d.mts → type-test-BvzWDJz3.d.mts} +1 -1
  161. package/dist/{type-test-sM7QpfQU.d.cts → type-test-CBK-iJ9d.d.cts} +1 -1
  162. package/dist/{utils-B8DsVgFr.d.mts → utils-1RyCGkpQ.d.mts} +1 -1
  163. package/dist/{utils-BfZkD2Pt.d.mts → utils-6Culwiaf.d.cts} +1 -1
  164. package/dist/{utils-DHQBNh-Z.d.cts → utils-CDJihcg3.d.mts} +1 -1
  165. package/dist/{utils-Bctk_WhH.d.cts → utils-nCQklGHV.d.cts} +1 -1
  166. package/dist/{uuid-Cusm2nIK.d.cts → uuid-CKFZfSff.d.mts} +1 -1
  167. package/dist/{uuid-ININPGKB.d.mts → uuid-D42A8UdP.d.cts} +1 -1
  168. package/dist/z-C0fpNWZg.d.cts +1 -0
  169. package/dist/z-D_jezYmm.d.mts +1 -0
  170. package/dist/{z-collection-BmuBin--.d.mts → z-collection-BSfgRU0Q.d.mts} +1 -1
  171. package/package.json +23 -27
  172. package/src/common/bin/lib0/decoding.spec.ts +84 -1
  173. package/src/common/bin/lib0/encoding.spec.ts +109 -1
  174. package/src/common/bin/lib0/string.spec.ts +45 -1
  175. package/src/common/crypto/crypto.spec.ts +7 -0
  176. package/src/common/crypto/xaes.spec.ts +48 -0
  177. package/src/common/data/deep.spec.ts +45 -0
  178. package/src/common/data/regexp.spec.ts +30 -0
  179. package/src/common/schema/export-json-schema.spec.ts +11 -7
  180. package/src/common/schema/export-json-schema.ts +59 -52
  181. package/src/common/schema/_sandbox/sandbox-inherit.ts +0 -13
  182. package/src/common/schema/_sandbox/sandbox.ts +0 -42
  183. package/src/common/schema/_sandbox/sandbox.xspec.ts +0 -45
  184. /package/dist/{index-BH1nuHdZ.d.cts → index-CIABef8t.d.mts} +0 -0
  185. /package/dist/{index-BL7o4fG9.d.cts → index-CliqZ9rj.d.mts} +0 -0
  186. /package/dist/{index-CP2eJYlK.d.mts → index-D6xqj1Qx.d.cts} +0 -0
  187. /package/dist/{index-DjOaHFU3.d.mts → index-DHFfG4yr.d.cts} +0 -0
  188. /package/dist/{index-sViox9YW.d.mts → index-N-OgGgfF.d.mts} +0 -0
  189. /package/dist/{z-ClMox7qS.d.mts → index-WOw4GVZo.d.cts} +0 -0
  190. /package/dist/{z-dtM4F8Lo.d.cts → index-luywJTzJ.d.mts} +0 -0
@@ -1,4 +1,5 @@
1
- import { createDecoder, peekUint8, peekUint16, peekUint32, peekVarInt, peekVarString, peekVarUint, readAny, readBigInt64, readBigUint64, readFloat32, readFloat64, readUint8, readUint16, readUint32, readUint32BigEndian, readVarInt, readVarString, readVarUint, readVarUint8Array } from './decoding'
1
+ import { afterEach, vi } from 'vitest'
2
+ import { clone, createDecoder, hasContent, peekUint8, peekUint16, peekUint32, peekVarInt, peekVarString, peekVarUint, readAny, readBigInt64, readBigUint64, readFloat32, readFloat64, readTailAsUint8Array, readUint8, readUint16, readUint32, readUint32BigEndian, readVarInt, readVarString, readVarUint, readVarUint8Array, skip8 } from './decoding'
2
3
  import { createBinEncoder, writeAny, writeBigInt64, writeBigUint64, writeFloat32, writeFloat64, writeUint8, writeUint16, writeUint32, writeVarInt, writeVarString, writeVarUint, writeVarUint8Array } from './encoding'
3
4
 
4
5
  describe('lib0/decoding', () => {
@@ -79,6 +80,88 @@ describe('lib0/decoding', () => {
79
80
  expect(readAny(d)).toEqual({ a: 1, b: 2 })
80
81
  })
81
82
 
83
+ it('hasContent reflects position', () => {
84
+ const d = createDecoder(new Uint8Array([1, 2]))
85
+ expect(hasContent(d)).toBe(true)
86
+ readUint8(d)
87
+ readUint8(d)
88
+ expect(hasContent(d)).toBe(false)
89
+ })
90
+
91
+ it('clone preserves and overrides position', () => {
92
+ const d = createDecoder(new Uint8Array([1, 2, 3]))
93
+ readUint8(d)
94
+ const c1 = clone(d)
95
+ expect(c1.pos).toBe(1)
96
+ expect(c1.arr).toBe(d.arr)
97
+ const c2 = clone(d, 0)
98
+ expect(c2.pos).toBe(0)
99
+ })
100
+
101
+ it('skip8 advances one byte', () => {
102
+ const d = createDecoder(new Uint8Array([7, 8]))
103
+ skip8(d)
104
+ expect(d.pos).toBe(1)
105
+ expect(readUint8(d)).toBe(8)
106
+ })
107
+
108
+ it('readTailAsUint8Array returns remaining bytes', () => {
109
+ const d = createDecoder(new Uint8Array([1, 2, 3, 4]))
110
+ readUint8(d)
111
+ const tail = readTailAsUint8Array(d)
112
+ expect([...tail]).toEqual([2, 3, 4])
113
+ })
114
+
115
+ it('readVarUint throws on unexpected end of array', () => {
116
+ const d = createDecoder(new Uint8Array([0x80, 0x80]))
117
+ expect(() => readVarUint(d)).toThrow(/Unexpected end of array/)
118
+ })
119
+
120
+ it('readVarInt throws on unexpected end of array', () => {
121
+ const d = createDecoder(new Uint8Array([0x80]))
122
+ expect(() => readVarInt(d)).toThrow(/Unexpected end of array/)
123
+ })
124
+
125
+ it('readVarUint throws on integer out of range', () => {
126
+ const bytes = new Uint8Array(12).fill(0xFF)
127
+ bytes[11] = 0x7F
128
+ const d = createDecoder(bytes)
129
+ expect(() => readVarUint(d)).toThrow(/Integer out of Range/)
130
+ })
131
+
132
+ it('readVarInt throws on integer out of range', () => {
133
+ const bytes = new Uint8Array(12).fill(0xFF)
134
+ bytes[11] = 0x7F
135
+ const d = createDecoder(bytes)
136
+ expect(() => readVarInt(d)).toThrow(/Integer out of Range/)
137
+ })
138
+
139
+ describe('polyfill path', () => {
140
+ afterEach(() => {
141
+ vi.unstubAllGlobals()
142
+ vi.resetModules()
143
+ })
144
+
145
+ it('readVarString via polyfill (empty, small, large)', async () => {
146
+ vi.stubGlobal('TextDecoder', undefined)
147
+ vi.resetModules()
148
+ const dec = await import('./decoding')
149
+ const enc = await import('./encoding')
150
+
151
+ const e = enc.createBinEncoder()
152
+ enc.writeVarString(e, '')
153
+ enc.writeVarString(e, 'abc')
154
+ const big = 'y'.repeat(15000)
155
+ enc.writeVarString(e, big)
156
+ const arr = enc.encodeToUint8Array(e)
157
+
158
+ const d = dec.createDecoder(arr)
159
+ expect(dec.readVarString(d)).toBe('')
160
+ expect(dec.readVarString(d)).toBe('abc')
161
+ expect(dec.readVarString(d)).toBe(big)
162
+ })
163
+ })
164
+
82
165
  it('should peek values', () => {
83
166
  const e = createBinEncoder()
84
167
  writeUint8(e, 42)
@@ -1,4 +1,6 @@
1
- import { createBinEncoder, encodeToUint8Array, isNegativeZero, setUint8, setUint16, setUint32, writeAny, writeBigInt64, writeBigUint64, writeFloat32, writeFloat64, writeUint8, writeUint8Array, writeUint16, writeUint32, writeUint32BigEndian, writeVarInt, writeVarString, writeVarUint, writeVarUint8Array } from './encoding'
1
+ import { afterEach, vi } from 'vitest'
2
+ import { createDecoder, readAny, readVarInt as readVarIntDec, readVarString } from './decoding'
3
+ import { createBinEncoder, encodeToUint8Array, isNegativeZero, length, setUint8, setUint16, setUint32, verifyLen, writeAny, writeBigInt64, writeBigUint64, writeBinaryEncoder, writeFloat32, writeFloat64, writeUint8, writeUint8Array, writeUint16, writeUint32, writeUint32BigEndian, writeVarInt, writeVarString, writeVarUint, writeVarUint8Array } from './encoding'
2
4
 
3
5
  describe('lib0/encoding', () => {
4
6
  it('should encode/decode uint8/16/32', () => {
@@ -84,4 +86,110 @@ describe('lib0/encoding', () => {
84
86
  expect(isNegativeZero(1)).toBe(false)
85
87
  expect(isNegativeZero(-1)).toBe(true)
86
88
  })
89
+
90
+ it('grows buffers when exceeding initial capacity', () => {
91
+ const e = createBinEncoder()
92
+ for (let i = 0; i < 250; i++) writeUint8(e, i & 0xFF)
93
+ expect(length(e)).toBe(250)
94
+ expect(e.bufs.length).toBeGreaterThan(0)
95
+ const arr = encodeToUint8Array(e)
96
+ expect(arr.length).toBe(250)
97
+ expect(arr[0]).toBe(0)
98
+ expect(arr[249]).toBe(249 & 0xFF)
99
+ })
100
+
101
+ it('verifyLen allocates a fresh buffer when required', () => {
102
+ const e = createBinEncoder()
103
+ writeUint8(e, 1)
104
+ verifyLen(e, 200)
105
+ expect(e.bufs.length).toBe(1)
106
+ writeUint8(e, 2)
107
+ const arr = encodeToUint8Array(e)
108
+ expect(arr[0]).toBe(1)
109
+ expect(arr[1]).toBe(2)
110
+ })
111
+
112
+ it('set updates bytes across multiple buffers', () => {
113
+ const e = createBinEncoder()
114
+ for (let i = 0; i < 250; i++) writeUint8(e, 0)
115
+ setUint8(e, 0, 0xAA)
116
+ setUint8(e, 120, 0xBB)
117
+ setUint8(e, 240, 0xCC)
118
+ const arr = encodeToUint8Array(e)
119
+ expect(arr[0]).toBe(0xAA)
120
+ expect(arr[120]).toBe(0xBB)
121
+ expect(arr[240]).toBe(0xCC)
122
+ })
123
+
124
+ it('writeUint8Array splits across buffers', () => {
125
+ const e = createBinEncoder()
126
+ writeUint8(e, 9)
127
+ const data = new Uint8Array(300)
128
+ for (let i = 0; i < data.length; i++) data[i] = i & 0xFF
129
+ writeUint8Array(e, data)
130
+ const arr = encodeToUint8Array(e)
131
+ expect(arr.length).toBe(301)
132
+ expect(arr[0]).toBe(9)
133
+ expect(arr[1]).toBe(0)
134
+ expect(arr[300]).toBe(299 & 0xFF)
135
+ })
136
+
137
+ it('writeBinaryEncoder appends another encoder', () => {
138
+ const inner = createBinEncoder()
139
+ writeUint8(inner, 1)
140
+ writeUint8(inner, 2)
141
+ const outer = createBinEncoder()
142
+ writeUint8(outer, 0)
143
+ writeBinaryEncoder(outer, inner)
144
+ const arr = encodeToUint8Array(outer)
145
+ expect([...arr]).toEqual([0, 1, 2])
146
+ })
147
+
148
+ it('writes long strings via alternate path', () => {
149
+ const e = createBinEncoder()
150
+ const big = 'z'.repeat(15000)
151
+ writeVarString(e, big)
152
+ const arr = encodeToUint8Array(e)
153
+ const d = createDecoder(arr)
154
+ expect(readVarString(d)).toBe(big)
155
+ })
156
+
157
+ it('writeVarInt handles multi-byte large values', () => {
158
+ const e = createBinEncoder()
159
+ writeVarInt(e, 1_000_000)
160
+ writeVarInt(e, -1_000_000)
161
+ const arr = encodeToUint8Array(e)
162
+ const d = createDecoder(arr)
163
+ expect(readVarIntDec(d)).toBe(1_000_000)
164
+ expect(readVarIntDec(d)).toBe(-1_000_000)
165
+ })
166
+
167
+ it('writeAny encodes float32-representable numbers compactly', () => {
168
+ const e = createBinEncoder()
169
+ writeAny(e, 0.5)
170
+ const arr = encodeToUint8Array(e)
171
+ expect(arr[0]).toBe(124)
172
+ const d = createDecoder(arr)
173
+ expect(readAny(d)).toBe(0.5)
174
+ })
175
+
176
+ describe('polyfill path', () => {
177
+ afterEach(() => {
178
+ vi.unstubAllGlobals()
179
+ vi.resetModules()
180
+ })
181
+
182
+ it('writeVarString via polyfill when TextEncoder missing', async () => {
183
+ vi.stubGlobal('TextEncoder', undefined)
184
+ vi.stubGlobal('TextDecoder', undefined)
185
+ vi.resetModules()
186
+ const enc = await import('./encoding')
187
+ const dec = await import('./decoding')
188
+ const e = enc.createBinEncoder()
189
+ enc.writeVarString(e, 'hi✓')
190
+ const arr = enc.encodeToUint8Array(e)
191
+ const d = dec.createDecoder(arr)
192
+ expect(dec.readVarString(d)).toBe('hi✓')
193
+ })
194
+ })
87
195
  })
@@ -1,4 +1,5 @@
1
- import { decodeUtf8, encodeUtf8, fromCamelCase, splice, trimLeft, utf8ByteLength } from './string'
1
+ import { afterEach, vi } from 'vitest'
2
+ import { _encodeUtf8Polyfill, decodeUtf8, encodeUtf8, fromCamelCase, splice, trimLeft, utf8ByteLength } from './string'
2
3
 
3
4
  describe('lib0/string', () => {
4
5
  it('should trim left', () => {
@@ -31,4 +32,47 @@ describe('lib0/string', () => {
31
32
  expect(splice('abcdef', 0, 3, 'Z')).toBe('Zdef')
32
33
  expect(splice('abcdef', 3, 0, 'Q')).toBe('abcQdef')
33
34
  })
35
+
36
+ it('should encode utf8 via polyfill', () => {
37
+ const bytes = _encodeUtf8Polyfill('hi✓')
38
+ expect(bytes).toBeInstanceOf(Uint8Array)
39
+ expect(decodeUtf8(bytes)).toBe('hi✓')
40
+ })
41
+
42
+ describe('polyfill paths via module reset', () => {
43
+ afterEach(() => {
44
+ vi.unstubAllGlobals()
45
+ vi.resetModules()
46
+ })
47
+
48
+ it('uses polyfill when TextEncoder/TextDecoder unavailable', async () => {
49
+ vi.stubGlobal('TextEncoder', undefined)
50
+ vi.stubGlobal('TextDecoder', undefined)
51
+ vi.resetModules()
52
+ const mod = await import('./string')
53
+ const encoded = mod.encodeUtf8('hello✓')
54
+ expect(encoded).toBeInstanceOf(Uint8Array)
55
+ expect(mod.decodeUtf8(encoded)).toBe('hello✓')
56
+ expect(mod.getUtf8TextEncoder()).toBeNull()
57
+ })
58
+
59
+ it('decodes via polyfill for a large buffer', async () => {
60
+ vi.stubGlobal('TextDecoder', undefined)
61
+ vi.resetModules()
62
+ const mod = await import('./string')
63
+ const big = 'a'.repeat(15000)
64
+ const bytes = new TextEncoder().encode(big)
65
+ expect(mod.decodeUtf8(bytes)).toBe(big)
66
+ })
67
+
68
+ it('disables broken TextDecoder (Safari BOM workaround)', async () => {
69
+ class FakeDecoder {
70
+ decode() { return 'x' }
71
+ }
72
+ vi.stubGlobal('TextDecoder', FakeDecoder as any)
73
+ vi.resetModules()
74
+ const mod = await import('./string')
75
+ expect(mod.getUtf8TextDecoder()).toBeNull()
76
+ })
77
+ })
34
78
  })
@@ -84,6 +84,13 @@ describe('crypto', () => {
84
84
  expect(typeof key).toBe('object')
85
85
  })
86
86
 
87
+ it('should derive keys without salt (default branch)', async () => {
88
+ const key = await deriveKeyPbkdf2(new Uint8Array([1, 2, 3]))
89
+ expect(key).toBeDefined()
90
+ const keyCbc = await (await import('./crypto')).deriveKeyPbkdf2CBC(new Uint8Array([1, 2, 3]))
91
+ expect(keyCbc).toBeDefined()
92
+ })
93
+
87
94
  it('should handle zero-length random and digest', async () => {
88
95
  expect(randomUint8Array(0)).toEqual(new Uint8Array(0))
89
96
  expect((await digest(new Uint8Array(0))).length).toBeGreaterThan(0)
@@ -80,6 +80,54 @@ describe('xaes.spec', () => {
80
80
  expect(new Uint8Array(decrypted)).toEqual(plaintext)
81
81
  })
82
82
 
83
+ it('xaes rejects wrong algorithm key', async () => {
84
+ const key = await crypto.subtle.generateKey(
85
+ { name: 'AES-GCM', length: 256 },
86
+ false,
87
+ ['encrypt', 'decrypt'],
88
+ )
89
+ const iv = new Uint8Array(24)
90
+ await expect(encryptXAES({ iv }, key, new Uint8Array(1))).rejects.toThrow(/AES-CBC/)
91
+ })
92
+
93
+ it('xaes rejects key without encrypt usage', async () => {
94
+ const key = await crypto.subtle.importKey(
95
+ 'raw',
96
+ new Uint8Array(32).fill(0x05),
97
+ { name: 'AES-CBC', length: 256 },
98
+ false,
99
+ ['decrypt'],
100
+ )
101
+ const iv = new Uint8Array(24)
102
+ await expect(encryptXAES({ iv }, key, new Uint8Array(1))).rejects.toThrow(/encrypt/)
103
+ })
104
+
105
+ it('xaes rejects key of wrong length', async () => {
106
+ const key = await crypto.subtle.importKey(
107
+ 'raw',
108
+ new Uint8Array(16).fill(0x06),
109
+ { name: 'AES-CBC', length: 128 },
110
+ false,
111
+ ['encrypt', 'decrypt'],
112
+ )
113
+ const iv = new Uint8Array(24)
114
+ await expect(encryptXAES({ iv }, key, new Uint8Array(1))).rejects.toThrow(/256 bits/)
115
+ })
116
+
117
+ it('xaes rejects iv of wrong length', async () => {
118
+ const key = await generateKeyXAES()
119
+ await expect(encryptXAES({ iv: new Uint8Array(12) }, key, new Uint8Array(1))).rejects.toThrow(/24 bytes/)
120
+ })
121
+
122
+ it('xaes accepts iv as ArrayBuffer', async () => {
123
+ const key = await generateKeyXAES()
124
+ const ivBuffer = new Uint8Array(24).fill(7).buffer
125
+ const data = new Uint8Array(10).fill(2)
126
+ const encrypted = await encryptXAES({ iv: ivBuffer }, key, data)
127
+ const decrypted = await decryptXAES({ iv: ivBuffer }, key, encrypted)
128
+ expect(new Uint8Array(decrypted)).toEqual(data)
129
+ })
130
+
83
131
  // it('xaes test vector, accumulated', async () => {
84
132
  // const hash = new SHAKE128()
85
133
  // const rng = new SHAKE128()
@@ -174,6 +174,51 @@ describe('deep', () => {
174
174
  // // expect(a.one.sample.a === b.one.sample.a).toBe(true)
175
175
  // })
176
176
 
177
+ it('deepEqual handles branch cases', () => {
178
+ expect(deepEqual(1, 2)).toBe(false)
179
+ expect(deepEqual(null, {})).toBe(false)
180
+ expect(deepEqual({}, null)).toBe(false)
181
+ class A { x = 1 }
182
+ class B { x = 1 }
183
+ expect(deepEqual(new A(), new B())).toBe(false)
184
+ expect(deepEqual({ a: 1 }, { b: 1 })).toBe(false)
185
+ expect(deepEqual({ a: 1 }, { a: 1, b: 2 })).toBe(false)
186
+ expect(deepEqual({ a: 1, b: 2 }, { a: 1, c: 2 })).toBe(false)
187
+ expect(deepEqual({ a: 1 }, { a: 1 })).toBe(true)
188
+
189
+ const proto = { inherited: 1 }
190
+ const x: any = Object.create(proto)
191
+ x.own = 1
192
+ const y: any = Object.create(proto)
193
+ y.own = 1
194
+ expect(deepEqual(x, y)).toBe(true)
195
+ })
196
+
197
+ it('deepStripUndefinedInPlace handles cycles and primitives', () => {
198
+ expect(deepStripUndefinedInPlace(5)).toBe(5)
199
+ const cyc: any = { a: 1 }
200
+ cyc.self = cyc
201
+ const result = deepStripUndefinedInPlace(cyc)
202
+ expect(result).toBe(cyc)
203
+ expect(cyc.a).toBe(1)
204
+ const obj: any = Object.create({ inherited: 1 })
205
+ obj.own = undefined
206
+ obj.keep = 2
207
+ deepStripUndefinedInPlace(obj)
208
+ expect('own' in obj).toBe(false)
209
+ expect(obj.keep).toBe(2)
210
+ })
211
+
212
+ it('deepMerge handles non-object target and source', () => {
213
+ expect(deepMerge(null as any, { a: 1 })).toEqual({ a: 1 })
214
+ expect(deepMerge({ a: 1 }, null)).toEqual({ a: 1 })
215
+ expect(deepMerge({ a: 1 }, 'str' as any)).toEqual({ a: 1 })
216
+ })
217
+
218
+ it('deepMerge concatenates arrays', () => {
219
+ expect(deepMerge({ list: [1, 2] }, { list: [3, 4] })).toEqual({ list: [1, 2, 3, 4] })
220
+ })
221
+
177
222
  it('should strip undefined', () => {
178
223
  const sample = {
179
224
  hello: {
@@ -0,0 +1,30 @@
1
+ import { escapeRegExp } from './regexp'
2
+
3
+ describe('escapeRegExp', () => {
4
+ it('returns empty string for falsy input', () => {
5
+ expect(escapeRegExp('')).toBe('')
6
+ // @ts-expect-error testing falsy
7
+ expect(escapeRegExp(undefined)).toBe('')
8
+ // @ts-expect-error testing falsy
9
+ expect(escapeRegExp(null)).toBe('')
10
+ })
11
+
12
+ it('returns source of RegExp input', () => {
13
+ expect(escapeRegExp(/foo\.bar/)).toBe('foo\\.bar')
14
+ })
15
+
16
+ it('escapes all special characters', () => {
17
+ expect(escapeRegExp('\\-[]/{}()*+?.^$|')).toBe('\\\\\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\^\\$\\|')
18
+ })
19
+
20
+ it('leaves normal characters alone', () => {
21
+ expect(escapeRegExp('hello world 123')).toBe('hello world 123')
22
+ })
23
+
24
+ it('escaped string works as literal in RegExp', () => {
25
+ const src = 'a.b+c'
26
+ const re = new RegExp(escapeRegExp(src))
27
+ expect(re.test('a.b+c')).toBe(true)
28
+ expect(re.test('axbxc')).toBe(false)
29
+ })
30
+ })
@@ -171,11 +171,15 @@ describe('json-schema.spec', () => {
171
171
  "type": "string",
172
172
  },
173
173
  "value": Object {
174
- "description": "The value to compare against",
175
- "type": Array [
176
- "string",
177
- "number",
174
+ "anyOf": Array [
175
+ Object {
176
+ "type": "string",
177
+ },
178
+ Object {
179
+ "type": "number",
180
+ },
178
181
  ],
182
+ "description": "The value to compare against",
179
183
  },
180
184
  },
181
185
  "required": Array [
@@ -233,9 +237,9 @@ describe('json-schema.spec', () => {
233
237
  description: 'A comparison operator',
234
238
  },
235
239
  value: {
236
- type: [
237
- 'string',
238
- 'number',
240
+ anyOf: [
241
+ { type: 'string' },
242
+ { type: 'number' },
239
243
  ],
240
244
  description: 'The value to compare against',
241
245
  },
@@ -1,72 +1,79 @@
1
1
  import type { Type } from './schema'
2
2
  import { isEmpty } from '../data'
3
- import { objectMap } from '../data/object'
4
3
 
5
- const _mapJsonSchemaType: Record<string, string> = {
4
+ const _primitiveMap: Record<string, string> = {
6
5
  string: 'string',
7
6
  number: 'number',
8
- boolean: 'boolean',
9
7
  int: 'integer',
8
+ boolean: 'boolean',
10
9
  }
11
10
 
12
- export function schemaExportJsonSchema<T>(schema: Type<T>): Record<string, any> {
13
- // assert(isSchemaObjectFlat(schema), 'schema should be a flat object')
11
+ function transformSchema(schema: Type<any>): Record<string, any> {
12
+ const out: Record<string, any> = {}
14
13
 
15
- function transformSchema(schema: Type<any>): any {
16
- const type = _mapJsonSchemaType[schema.type] ?? schema.type ?? 'object'
14
+ if (schema._enumValues) {
15
+ out.type = _primitiveMap[schema.type] ?? schema.type
16
+ out.enum = [...schema._enumValues]
17
+ }
18
+ else if (schema.type === 'literal') {
19
+ out.const = schema._default
20
+ }
21
+ else if (schema.type === 'union' && Array.isArray(schema._union)) {
22
+ out.anyOf = schema._union.map((s: Type<any>) => transformSchema(s))
23
+ }
24
+ else if (schema.type === 'object' && schema._object) {
25
+ out.type = 'object'
17
26
  const properties: Record<string, any> = {}
18
27
  const required: string[] = []
19
-
20
- objectMap(schema._object!, (key, schema: any) => {
21
- const type = _mapJsonSchemaType[schema.type] ?? schema.type
22
- properties[key] = { type }
23
- const enumValues = (schema as any)._enumValues
24
- if (enumValues) {
25
- properties[key].enum = enumValues
26
- }
27
- if (schema._default !== undefined) {
28
- properties[key].default = schema._default
29
- }
30
- if (schema._meta?.desc) {
31
- properties[key].description = schema._meta.desc
32
- }
33
- if (schema._optional !== true) {
28
+ for (const key of Object.keys(schema._object)) {
29
+ const propSchema = schema._object[key] as Type<any>
30
+ properties[key] = transformSchema(propSchema)
31
+ if (propSchema._optional !== true)
34
32
  required.push(key)
35
- }
36
- if (schema.type === 'array' && schema._type) {
37
- properties[key].items = transformSchema(schema._type)
38
- }
39
- else if (schema.type === 'object' && schema._object) {
40
- Object.assign(properties[key], transformSchema(schema))
41
- properties[key].additionalProperties = false
42
- }
43
- else if (schema.type === 'record' && schema._type) {
44
- properties[key].type = 'object'
45
- properties[key].additionalProperties = transformSchema(schema._type)
46
- }
47
- // Handle union types (e.g., z.union)
48
- else if (schema.type === 'union' && Array.isArray(schema._union)) {
49
- properties[key].type = schema._union.map((s: any) => _mapJsonSchemaType[s.type] ?? s.type) // todo complex types
50
- }
51
- })
52
-
53
- if (!isEmpty(properties)) {
54
- return {
55
- type,
56
- properties,
57
- additionalProperties: false,
58
- ...(required.length > 0 ? { required } : {}),
59
- }
60
- }
61
-
62
- return {
63
- type,
64
33
  }
34
+ if (!isEmpty(properties))
35
+ out.properties = properties
36
+ out.additionalProperties = false
37
+ if (required.length > 0)
38
+ out.required = required
65
39
  }
40
+ else if (schema.type === 'record' && schema._type) {
41
+ out.type = 'object'
42
+ out.additionalProperties = transformSchema(schema._type)
43
+ }
44
+ else if (schema.type === 'array' && schema._type) {
45
+ out.type = 'array'
46
+ out.items = transformSchema(schema._type)
47
+ }
48
+ else if (schema.type === 'tuple' && Array.isArray(schema._type)) {
49
+ out.type = 'array'
50
+ out.items = (schema._type as Type<any>[]).map(s => transformSchema(s))
51
+ out.minItems = schema._type.length
52
+ out.maxItems = schema._type.length
53
+ }
54
+ else if (schema.type === 'none') {
55
+ out.type = 'null'
56
+ }
57
+ else if (schema.type === 'any') {
58
+ // no constraint
59
+ }
60
+ else {
61
+ const t = _primitiveMap[schema.type]
62
+ if (t)
63
+ out.type = t
64
+ }
65
+
66
+ if (schema._default !== undefined && schema.type !== 'literal')
67
+ out.default = schema._default
68
+ if (schema._meta?.desc)
69
+ out.description = schema._meta.desc
66
70
 
71
+ return out
72
+ }
73
+
74
+ export function schemaExportJsonSchema<T>(schema: Type<T>): Record<string, any> {
67
75
  return {
68
76
  $schema: 'http://json-schema.org/draft-07/schema#',
69
- additionalProperties: false,
70
77
  ...transformSchema(schema),
71
78
  }
72
79
  }
@@ -1,13 +0,0 @@
1
- // class TypeClass<T = unknown> {
2
- // optional(): TypeClass<T | undefined> {
3
- // return this
4
- // }
5
- // }
6
-
7
- // class TypeStringClass<T extends string> extends TypeClass<T> {
8
-
9
- // }
10
-
11
- // const o = new TypeStringClass()
12
- // const v = o.optional()
13
- // type t = typeof v // expect: TypeStringClass<string | undefined>
@@ -1,42 +0,0 @@
1
- // // Function
2
-
3
- // interface Type<T = unknown> {
4
- // _value?: T
5
- // }
6
-
7
- // type Infer<T> = T extends Type<infer TT> ? TT : never
8
-
9
- // type TupleOutput<T extends Type[]> = {
10
- // [K in keyof T]: T[K] extends Type<infer U> ? U : never;
11
- // }
12
-
13
- // type ArrayOutput<Head extends Type[], Rest extends Type | undefined> = [
14
- // ...TupleOutput<Head>,
15
- // ...(Rest extends Type ? Infer<Rest>[] : []),
16
- // ]
17
-
18
- // type ArrayType<
19
- // Head extends Type[] = Type[],
20
- // Rest extends Type | undefined = Type | undefined,
21
- // > = Type<ArrayOutput<Head, Rest>>
22
-
23
- // function tuple<T extends [] | [Type, ...Type[]]>(items: T): ArrayType<T, undefined> {
24
- // return {} as any
25
- // }
26
-
27
- // function string(): Type<string> {
28
- // return {} as any
29
- // }
30
-
31
- // function boolean(): Type<boolean> {
32
- // return {} as any
33
- // }
34
-
35
- // function number(): Type<number> {
36
- // return {} as any
37
- // }
38
-
39
- // const tt = tuple([number(), string(), boolean()])
40
- // type ttt = Infer<typeof tt> // expected [number, string, boolean]
41
-
42
- // //