kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
fix: make quantifier lazy to not span multiple JSON blocks, tests + docs
rodzic
5b510116e4
commit
07138c9ca7
40
src/utils.ts
40
src/utils.ts
|
@ -2,18 +2,39 @@ import { customAlphabet, urlAlphabet } from 'nanoid'
|
|||
|
||||
import * as types from './types'
|
||||
|
||||
/**
|
||||
* Extracts the first JSON object string from a given string.
|
||||
*
|
||||
* @param text - string from which to extract the JSON object
|
||||
* @returns extracted JSON object string, or `undefined` if no JSON object is found
|
||||
*/
|
||||
export function extractJSONObjectFromString(text: string): string | undefined {
|
||||
return text.match(/\{(.|\n)*\}/gm)?.[0]
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the first JSON array string from a given string.
|
||||
*
|
||||
* @param text - string from which to extract the JSON array
|
||||
* @returns extracted JSON array string, or `undefined` if no JSON array is found
|
||||
*/
|
||||
export function extractJSONArrayFromString(text: string): string | undefined {
|
||||
return text.match(/\[(.|\n)*\]/gm)?.[0]
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the execution of a function for a specified time.
|
||||
*
|
||||
* @param ms - number of milliseconds to pause
|
||||
* @returns promise that resolves after the specified number of milliseconds
|
||||
*/
|
||||
export function sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
/**
|
||||
* A default ID generator function that uses a custom alphabet based on URL safe symbols.
|
||||
*/
|
||||
export const defaultIDGeneratorFn: types.IDGeneratorFunction =
|
||||
customAlphabet(urlAlphabet)
|
||||
|
||||
|
@ -23,28 +44,27 @@ export function isValidTaskIdentifier(id: string): boolean {
|
|||
}
|
||||
|
||||
/**
|
||||
* Chunk a string into an array of strings of a given length
|
||||
* Chunks a string into an array of chunks.
|
||||
*
|
||||
* @param text - string to chunk
|
||||
* @param length - maximum length of each chunk
|
||||
* @returns array of strings
|
||||
* @param maxLength - maximum length of each chunk
|
||||
* @returns array of chunks
|
||||
*/
|
||||
export const chunkString = (text: string, length: number) => {
|
||||
export const chunkString = (text: string, maxLength: number) => {
|
||||
const words = text.split(' ')
|
||||
const chunks: string[] = []
|
||||
let chunk = ''
|
||||
|
||||
for (const word of words) {
|
||||
if (word.length > length) {
|
||||
if (word.length > maxLength) {
|
||||
// Truncate the word if it's too long and indicate that it was truncated:
|
||||
chunks.push(word.substring(0, length - 3) + '...')
|
||||
}
|
||||
|
||||
if ((chunk + word).length > length) {
|
||||
chunks.push(word.substring(0, maxLength - 3) + '...')
|
||||
} else if ((chunk + word + 1).length > maxLength) {
|
||||
// +1 accounts for the space between words
|
||||
chunks.push(chunk.trim())
|
||||
chunk = word
|
||||
} else {
|
||||
chunk += ' ' + word
|
||||
chunk += (chunk ? ' ' : '') + word
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
import test from 'ava'
|
||||
|
||||
import { isValidTaskIdentifier } from '@/utils'
|
||||
import {
|
||||
chunkString,
|
||||
defaultIDGeneratorFn,
|
||||
extractJSONArrayFromString,
|
||||
extractJSONObjectFromString,
|
||||
isValidTaskIdentifier,
|
||||
sleep
|
||||
} from '@/utils'
|
||||
|
||||
test('isValidTaskIdentifier - valid', async (t) => {
|
||||
t.true(isValidTaskIdentifier('foo'))
|
||||
|
@ -18,3 +25,53 @@ test('isValidTaskIdentifier - invalid', async (t) => {
|
|||
t.false(isValidTaskIdentifier('x'.repeat(65)))
|
||||
t.false(isValidTaskIdentifier('-foo'))
|
||||
})
|
||||
|
||||
test('extractJSONObjectFromString should extract first JSON object from string', (t) => {
|
||||
const jsonString = '{"name":"John"} Some other text {"name":"Doe"}'
|
||||
const result = extractJSONObjectFromString(jsonString)
|
||||
t.is(result, '{"name":"John"}')
|
||||
})
|
||||
|
||||
test('extractJSONArrayFromString should extract first JSON array from string', (t) => {
|
||||
const jsonString = '[1,2,3] Some other text [4,5,6]'
|
||||
const result = extractJSONArrayFromString(jsonString)
|
||||
t.is(result, '[1,2,3]')
|
||||
})
|
||||
|
||||
test('extractJSONObjectFromString should return undefined if no JSON object is found', (t) => {
|
||||
const jsonString = 'Some text'
|
||||
const result = extractJSONObjectFromString(jsonString)
|
||||
t.is(result, undefined)
|
||||
})
|
||||
|
||||
test('extractJSONArrayFromString should return undefined if no JSON array is found', (t) => {
|
||||
const jsonString = 'Some text'
|
||||
const result = extractJSONArrayFromString(jsonString)
|
||||
t.is(result, undefined)
|
||||
})
|
||||
|
||||
test('sleep should delay execution', async (t) => {
|
||||
const start = Date.now()
|
||||
await sleep(1000) // for example, 1000ms / 1sec
|
||||
const end = Date.now()
|
||||
t.true(end - start >= 1000)
|
||||
})
|
||||
|
||||
test('defaultIDGeneratorFn should generate URL-safe string', (t) => {
|
||||
const result = defaultIDGeneratorFn()
|
||||
|
||||
// Check if generated string matches URL-safe characters:
|
||||
t.regex(result, /^[A-Za-z0-9\-_]+$/)
|
||||
})
|
||||
|
||||
test('chunkString should split string into chunks', (t) => {
|
||||
const text = 'Hello, this is a test string for chunkString function.'
|
||||
const chunks = chunkString(text, 12)
|
||||
t.deepEqual(chunks, [
|
||||
'Hello, this',
|
||||
'is a test',
|
||||
'string for',
|
||||
'chunkString',
|
||||
'function.'
|
||||
])
|
||||
})
|
||||
|
|
Ładowanie…
Reference in New Issue