Merge branch 'hoppscotch:main' into codeday/main

This commit is contained in:
Jason Jock Nava Casareno
2022-08-12 15:45:10 -07:00
committed by GitHub
8 changed files with 394 additions and 82 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@hoppscotch/data",
"version": "0.4.2",
"version": "0.4.3",
"description": "Data Types, Validations and Migrations for Hoppscotch Public Data Structures",
"main": "dist/index.js",
"module": "true",

View File

@@ -8,6 +8,12 @@ import * as E from "fp-ts/Either"
import * as P from "parser-ts/Parser"
import * as S from "parser-ts/string"
import * as C from "parser-ts/char"
import { recordUpdate } from "./utils/record"
/**
* Special characters in the Raw Key Value Grammar
*/
const SPECIAL_CHARS = ["#", ":"] as const
export type RawKeyValueEntry = {
key: string
@@ -31,14 +37,31 @@ const stringTakeUntilCharsInclusive = flow(
P.chainFirst(() => P.sat(() => true)),
)
const quotedString = pipe(
S.doubleQuotedString,
P.map((x) => JSON.parse(`"${x}"`))
)
const key = pipe(
stringTakeUntilChars([":", "\n"]),
P.map(Str.trim)
wsSurround(quotedString),
P.alt(() =>
pipe(
stringTakeUntilChars([":", "\n"]),
P.map(Str.trim)
)
)
)
const value = pipe(
stringTakeUntilChars(["\n"]),
P.map(Str.trim)
wsSurround(quotedString),
P.alt(() =>
pipe(
stringTakeUntilChars(["\n"]),
P.map(Str.trim)
)
)
)
const commented = pipe(
@@ -105,6 +128,37 @@ const tolerantFile = pipe(
/* End of Parser Definitions */
/**
* Detect whether the string needs to have escape characters in raw key value strings
* @param input The string to check against
*/
const stringNeedsEscapingForRawKVString = (input: string) => {
// If there are any of our special characters, it needs to be escaped definitely
if (SPECIAL_CHARS.some((x) => input.includes(x)))
return true
// The theory behind this impl is that if we apply JSON.stringify on a string
// it does escaping and then return a JSON string representation.
// We remove the quotes of the JSON and see if it can be matched against the input string
const stringified = JSON.stringify(input)
const y = stringified
.substring(1, stringified.length - 1)
.trim()
return y !== input
}
/**
* Applies Raw Key Value escaping (via quotes + escape chars) if needed
* @param input The input to apply escape on
* @returns If needed, the escaped string, else the input string itself
*/
const applyEscapeIfNeeded = (input: string) =>
stringNeedsEscapingForRawKVString(input)
? JSON.stringify(input)
: input
/**
* Converts Raw Key Value Entries to the file string format
* @param entries The entries array
@@ -113,8 +167,13 @@ const tolerantFile = pipe(
export const rawKeyValueEntriesToString = (entries: RawKeyValueEntry[]) =>
pipe(
entries,
A.map(({ key, value, active }) =>
active ? `${key}: ${value}` : `# ${key}: ${value}`
A.map(
flow(
recordUpdate("key", applyEscapeIfNeeded),
recordUpdate("value", applyEscapeIfNeeded),
({ key, value, active }) =>
active ? `${(key)}: ${value}` : `# ${key}: ${value}`
)
),
stringArrayJoin("\n")
)

View File

@@ -0,0 +1,17 @@
/**
* Modify a record value with a mapping function
* @param name The key to update
* @param func The value to update
* @returns The updated record
*/
export const recordUpdate =
<
X extends {},
K extends keyof X,
R
>(name: K, func: (input: X[K]) => R) =>
(x: X): Omit<X, K> & { [x in K]: R } => ({
...x,
[name]: func(x[name])
})