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.
- package/dist/{args-FLoL3OKJ.d.cts → args-CEjib9V9.d.mts} +1 -1
- package/dist/{args-WC9q5kz2.d.mts → args-DEig-jw4.d.cts} +1 -1
- package/dist/{clipboard-BkUO-syY.d.mts → clipboard-BusqmLLY.d.cts} +1 -1
- package/dist/{clipboard-Cfpr331X.d.cts → clipboard-DcuuFRwa.d.mts} +1 -1
- package/dist/common/exec/index.d.cts +2 -2
- package/dist/common/exec/index.d.mts +2 -2
- package/dist/common/exec/promise.d.cts +1 -1
- package/dist/common/exec/promise.d.mts +1 -1
- package/dist/common/exec/throttle-debounce.d.cts +1 -1
- package/dist/common/exec/throttle-debounce.d.mts +1 -1
- package/dist/common/index.cjs +21 -0
- package/dist/common/index.d.cts +14 -11
- package/dist/common/index.d.mts +15 -12
- package/dist/common/index.mjs +4 -1
- package/dist/common/msg/rpc.cjs +8 -8
- package/dist/common/msg/rpc.cjs.map +1 -1
- package/dist/common/msg/rpc.mjs +8 -8
- package/dist/common/msg/rpc.mjs.map +1 -1
- package/dist/common/schema/export-json-schema.cjs +40 -31
- package/dist/common/schema/export-json-schema.cjs.map +1 -1
- package/dist/common/schema/export-json-schema.mjs +40 -31
- package/dist/common/schema/export-json-schema.mjs.map +1 -1
- package/dist/common/schema/index.cjs +21 -0
- package/dist/common/schema/index.d.cts +6 -3
- package/dist/common/schema/index.d.mts +7 -4
- package/dist/common/schema/index.mjs +4 -1
- package/dist/common/schema/sql/expr.cjs +128 -0
- package/dist/common/schema/sql/expr.cjs.map +1 -0
- package/dist/common/schema/sql/expr.d.cts +2 -0
- package/dist/common/schema/sql/expr.d.mts +2 -0
- package/dist/common/schema/sql/expr.mjs +115 -0
- package/dist/common/schema/sql/expr.mjs.map +1 -0
- package/dist/common/schema/sql/index.cjs +23 -0
- package/dist/common/schema/sql/index.d.cts +4 -0
- package/dist/common/schema/sql/index.d.mts +4 -0
- package/dist/common/schema/sql/index.mjs +5 -0
- package/dist/common/schema/sql/select.cjs +143 -0
- package/dist/common/schema/sql/select.cjs.map +1 -0
- package/dist/common/schema/sql/select.d.cts +2 -0
- package/dist/common/schema/sql/select.d.mts +2 -0
- package/dist/common/schema/sql/select.mjs +139 -0
- package/dist/common/schema/sql/select.mjs.map +1 -0
- package/dist/common/schema/sql/table.cjs +23 -0
- package/dist/common/schema/sql/table.cjs.map +1 -0
- package/dist/common/schema/sql/table.d.cts +2 -0
- package/dist/common/schema/sql/table.d.mts +2 -0
- package/dist/common/schema/sql/table.mjs +20 -0
- package/dist/common/schema/sql/table.mjs.map +1 -0
- package/dist/common/schema/type-test.d.cts +1 -1
- package/dist/common/schema/type-test.d.mts +1 -1
- package/dist/common/schema/utils.d.cts +1 -1
- package/dist/common/schema/utils.d.mts +1 -1
- package/dist/common/schema/z.d.mts +1 -1
- package/dist/common/storage/index.d.cts +1 -1
- package/dist/common/storage/index.d.mts +1 -1
- package/dist/common/storage/memstorage.d.cts +1 -1
- package/dist/common/storage/memstorage.d.mts +1 -1
- package/dist/common/test.d.cts +1 -1
- package/dist/common/test.d.mts +1 -1
- package/dist/common/time.d.cts +1 -1
- package/dist/common/time.d.mts +1 -1
- package/dist/common/timeout.d.cts +1 -1
- package/dist/common/timeout.d.mts +1 -1
- package/dist/common/utils.d.cts +1 -1
- package/dist/common/utils.d.mts +1 -1
- package/dist/common/uuid.d.cts +1 -1
- package/dist/common/uuid.d.mts +1 -1
- package/dist/{crypto-CyTV7Qce.d.cts → crypto-D68rVmvU.d.mts} +1 -1
- package/dist/{crypto-LT7EC5_d.d.mts → crypto-KzGHoCJE.d.cts} +1 -1
- package/dist/{env-B3vOiVY8.d.cts → env-BJXdwBKq.d.mts} +1 -1
- package/dist/{env-C3npYe8w.d.mts → env-HsOnA_yK.d.cts} +1 -1
- package/dist/expr-CCKrqOw1.d.mts +25 -0
- package/dist/expr-yYgSeBZ3.d.cts +25 -0
- package/dist/{files-CDNKX9VI.d.mts → files-4O-PxnAC.d.cts} +1 -1
- package/dist/{files-DdI9UZvg.d.cts → files-BlpxqSTT.d.mts} +1 -1
- package/dist/{files-async-1V0bu_ca.d.cts → files-async-DFLC-Nkd.d.cts} +1 -1
- package/dist/{files-async-cBMkRwsu.d.mts → files-async-DfuEEDjH.d.mts} +1 -1
- package/dist/{filestorage-CXQ9MzeW.d.cts → filestorage-BjeBZEAs.d.cts} +1 -1
- package/dist/{filestorage-YzM2z9sU.d.mts → filestorage-CmfztpWm.d.mts} +1 -1
- package/dist/{fs-DHJ9AqUk.d.cts → fs-D837bjRT.d.cts} +1 -1
- package/dist/{fs-DgjZdpuF.d.mts → fs-DlYLapik.d.mts} +1 -1
- package/dist/{glob-Bfs7ZS_i.d.mts → glob-5yW09dkR.d.mts} +1 -1
- package/dist/{glob-Bt150jOY.d.cts → glob-CZaZPqiy.d.cts} +1 -1
- package/dist/index.all.cjs +21 -0
- package/dist/index.all.d.cts +28 -25
- package/dist/index.all.d.mts +29 -26
- package/dist/index.all.mjs +4 -1
- package/dist/index.browser.cjs +21 -0
- package/dist/index.browser.d.cts +14 -11
- package/dist/index.browser.d.mts +15 -12
- package/dist/index.browser.mjs +4 -1
- package/dist/index.jsr.d.cts +4 -4
- package/dist/index.jsr.d.mts +4 -4
- package/dist/index.node.cjs +21 -0
- package/dist/index.node.d.cts +28 -25
- package/dist/index.node.d.mts +29 -26
- package/dist/index.node.mjs +4 -1
- package/dist/{log-file-bsTsc9KM.d.cts → log-file-DwEDms1F.d.cts} +2 -2
- package/dist/{log-file-DTuImomJ.d.mts → log-file-QV1unm3z.d.mts} +2 -2
- package/dist/{log-file-rotation-_YruAcNc.d.cts → log-file-rotation-BpZxXYlU.d.cts} +2 -2
- package/dist/{log-file-rotation-FBmtp_Uz.d.mts → log-file-rotation-DanrO_2y.d.mts} +2 -2
- package/dist/{log-node-DlrXl3QO.d.mts → log-node-BSn7RqAc.d.mts} +1 -1
- package/dist/{log-node-Dk948mHX.d.cts → log-node-D_fiJL6x.d.cts} +1 -1
- package/dist/{log-rotation-CkyjZbK5.d.mts → log-rotation-BdGakFya.d.cts} +1 -1
- package/dist/{log-rotation-_d7iRm9s.d.cts → log-rotation-Ce4e-8LN.d.mts} +1 -1
- package/dist/{log-util-2Ls76P-0.d.cts → log-util-C0U3zCjw.d.cts} +1 -1
- package/dist/{log-util-Da_d19f8.d.mts → log-util-Da_UCcmt.d.mts} +1 -1
- package/dist/{memstorage-D5A9FwiP.d.mts → memstorage-BhWXthO8.d.mts} +1 -1
- package/dist/{memstorage-BcjQLdaQ.d.cts → memstorage-tvlWDYgS.d.cts} +1 -1
- package/dist/node/args.d.cts +1 -1
- package/dist/node/args.d.mts +1 -1
- package/dist/node/clipboard.d.cts +1 -1
- package/dist/node/clipboard.d.mts +1 -1
- package/dist/node/crypto.d.cts +1 -1
- package/dist/node/crypto.d.mts +1 -1
- package/dist/node/env.d.cts +1 -1
- package/dist/node/env.d.mts +1 -1
- package/dist/node/files-async.d.cts +1 -1
- package/dist/node/files-async.d.mts +1 -1
- package/dist/node/files.d.cts +1 -1
- package/dist/node/files.d.mts +1 -1
- package/dist/node/filestorage.d.cts +1 -1
- package/dist/node/filestorage.d.mts +1 -1
- package/dist/node/fs.d.cts +1 -1
- package/dist/node/fs.d.mts +1 -1
- package/dist/node/glob.d.cts +1 -1
- package/dist/node/glob.d.mts +1 -1
- package/dist/node/index.d.cts +14 -14
- package/dist/node/index.d.mts +14 -14
- package/dist/node/log/index.d.cts +5 -5
- package/dist/node/log/index.d.mts +5 -5
- package/dist/node/log/log-file-rotation.d.cts +1 -1
- package/dist/node/log/log-file-rotation.d.mts +1 -1
- package/dist/node/log/log-file.d.cts +1 -1
- package/dist/node/log/log-file.d.mts +1 -1
- package/dist/node/log/log-node.cjs +4 -13
- package/dist/node/log/log-node.cjs.map +1 -1
- package/dist/node/log/log-node.d.cts +1 -1
- package/dist/node/log/log-node.d.mts +1 -1
- package/dist/node/log/log-node.mjs +4 -13
- package/dist/node/log/log-node.mjs.map +1 -1
- package/dist/node/log/log-rotation.d.cts +1 -1
- package/dist/node/log/log-rotation.d.mts +1 -1
- package/dist/node/log/log-util.d.cts +1 -1
- package/dist/node/log/log-util.d.mts +1 -1
- package/dist/{promise-DGgiRckN.d.cts → promise-CU_CENbU.d.cts} +1 -1
- package/dist/{promise-MH3xAy4S.d.mts → promise-CoWXgo4w.d.mts} +1 -1
- package/dist/select-DrciHdk_.d.cts +52 -0
- package/dist/select-F2KpP6mo.d.mts +52 -0
- package/dist/table-Cr8tjDIL.d.mts +19 -0
- package/dist/table-IkLXirT-.d.cts +19 -0
- package/dist/{test-CAhm15f4.d.mts → test-DcXa0MeX.d.cts} +1 -1
- package/dist/{test-D2plOVHF.d.cts → test-jZsc7P2c.d.mts} +1 -1
- package/dist/{throttle-debounce-BLFxAZ8W.d.mts → throttle-debounce-CCh0F100.d.mts} +1 -1
- package/dist/{throttle-debounce-Psb0ay1r.d.cts → throttle-debounce-DyFiyoAk.d.cts} +1 -1
- package/dist/{time-BfKJBbym.d.cts → time-BgFZe9ys.d.cts} +1 -1
- package/dist/{time-DxE-vjjw.d.mts → time-DSV_k3mG.d.mts} +1 -1
- package/dist/{timeout-CnUk6Ruj.d.mts → timeout-DDSSNZY8.d.mts} +1 -1
- package/dist/{timeout-CpFcK8MD.d.cts → timeout-E3ZQbJgK.d.cts} +1 -1
- package/dist/{type-test-BiKyEZkc.d.mts → type-test-BvzWDJz3.d.mts} +1 -1
- package/dist/{type-test-sM7QpfQU.d.cts → type-test-CBK-iJ9d.d.cts} +1 -1
- package/dist/{utils-B8DsVgFr.d.mts → utils-1RyCGkpQ.d.mts} +1 -1
- package/dist/{utils-BfZkD2Pt.d.mts → utils-6Culwiaf.d.cts} +1 -1
- package/dist/{utils-DHQBNh-Z.d.cts → utils-CDJihcg3.d.mts} +1 -1
- package/dist/{utils-Bctk_WhH.d.cts → utils-nCQklGHV.d.cts} +1 -1
- package/dist/{uuid-Cusm2nIK.d.cts → uuid-CKFZfSff.d.mts} +1 -1
- package/dist/{uuid-ININPGKB.d.mts → uuid-D42A8UdP.d.cts} +1 -1
- package/dist/z-C0fpNWZg.d.cts +1 -0
- package/dist/z-D_jezYmm.d.mts +1 -0
- package/dist/{z-collection-BmuBin--.d.mts → z-collection-BSfgRU0Q.d.mts} +1 -1
- package/package.json +23 -27
- package/src/common/bin/lib0/decoding.spec.ts +84 -1
- package/src/common/bin/lib0/encoding.spec.ts +109 -1
- package/src/common/bin/lib0/string.spec.ts +45 -1
- package/src/common/crypto/crypto.spec.ts +7 -0
- package/src/common/crypto/xaes.spec.ts +48 -0
- package/src/common/data/deep.spec.ts +45 -0
- package/src/common/data/regexp.spec.ts +30 -0
- package/src/common/schema/export-json-schema.spec.ts +11 -7
- package/src/common/schema/export-json-schema.ts +59 -52
- package/src/common/schema/_sandbox/sandbox-inherit.ts +0 -13
- package/src/common/schema/_sandbox/sandbox.ts +0 -42
- package/src/common/schema/_sandbox/sandbox.xspec.ts +0 -45
- /package/dist/{index-BH1nuHdZ.d.cts → index-CIABef8t.d.mts} +0 -0
- /package/dist/{index-BL7o4fG9.d.cts → index-CliqZ9rj.d.mts} +0 -0
- /package/dist/{index-CP2eJYlK.d.mts → index-D6xqj1Qx.d.cts} +0 -0
- /package/dist/{index-DjOaHFU3.d.mts → index-DHFfG4yr.d.cts} +0 -0
- /package/dist/{index-sViox9YW.d.mts → index-N-OgGgfF.d.mts} +0 -0
- /package/dist/{z-ClMox7qS.d.mts → index-WOw4GVZo.d.cts} +0 -0
- /package/dist/{z-dtM4F8Lo.d.cts → index-luywJTzJ.d.mts} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
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 {
|
|
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 {
|
|
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
|
-
"
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
13
|
-
|
|
11
|
+
function transformSchema(schema: Type<any>): Record<string, any> {
|
|
12
|
+
const out: Record<string, any> = {}
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
// //
|