Compare commits
7 Commits
fix/nft-cr
...
feat/amoun
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4af3df017 | ||
|
|
5d8d142bc4 | ||
|
|
e27a71d713 | ||
|
|
e08b07cbeb | ||
|
|
e4936c03ef | ||
|
|
21a69ac8ea | ||
|
|
52e4f219f7 |
@@ -39,7 +39,7 @@ const Select = forwardRef<any, Props>((props, ref) => {
|
|||||||
return {
|
return {
|
||||||
...provided,
|
...provided,
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
width: '100%'
|
width: '100%',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
singleValue: provided => ({
|
singleValue: provided => ({
|
||||||
@@ -108,9 +108,10 @@ const Select = forwardRef<any, Props>((props, ref) => {
|
|||||||
dropdownIndicator: (provided, state) => {
|
dropdownIndicator: (provided, state) => {
|
||||||
return {
|
return {
|
||||||
...provided,
|
...provided,
|
||||||
|
padding: 6,
|
||||||
color: state.isFocused ? colors.border : colors.secondary,
|
color: state.isFocused ? colors.border : colors.secondary,
|
||||||
':hover': {
|
':hover': {
|
||||||
color: colors.border
|
color: colors.border,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,12 @@ import {
|
|||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
import state from '../../state'
|
import state from '../../state'
|
||||||
import { streamState } from '../DebugStream'
|
import { streamState } from '../DebugStream'
|
||||||
import { Button } from '..'
|
import { Box, Button } from '..'
|
||||||
import Textarea from '../Textarea'
|
import Textarea from '../Textarea'
|
||||||
import { getFlags } from '../../state/constants/flags'
|
import { getFlags } from '../../state/constants/flags'
|
||||||
import { Plus, Trash } from 'phosphor-react'
|
import { Plus, Trash } from 'phosphor-react'
|
||||||
import AccountSequence from '../Sequence'
|
import AccountSequence from '../Sequence'
|
||||||
|
import { typeIs } from '../../utils/helpers'
|
||||||
|
|
||||||
interface UIProps {
|
interface UIProps {
|
||||||
setState: (pTx?: Partial<TransactionState> | undefined) => TransactionState | undefined
|
setState: (pTx?: Partial<TransactionState> | undefined) => TransactionState | undefined
|
||||||
@@ -87,6 +88,22 @@ export const TxUI: FC<UIProps> = ({
|
|||||||
[setState, txFields]
|
[setState, txFields]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const setRawField = useCallback(
|
||||||
|
(field: keyof TxFields, type: string, value: any) => {
|
||||||
|
// TODO $type should be a narrowed type
|
||||||
|
setState({
|
||||||
|
txFields: {
|
||||||
|
...txFields,
|
||||||
|
[field]: {
|
||||||
|
$type: type,
|
||||||
|
$value: value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[setState, txFields]
|
||||||
|
)
|
||||||
|
|
||||||
const handleEstimateFee = useCallback(
|
const handleEstimateFee = useCallback(
|
||||||
async (state?: TransactionState, silent?: boolean) => {
|
async (state?: TransactionState, silent?: boolean) => {
|
||||||
setFeeLoading(true)
|
setFeeLoading(true)
|
||||||
@@ -134,6 +151,16 @@ export const TxUI: FC<UIProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const otherFields = Object.keys(txFields).filter(k => !richFields.includes(k)) as [keyof TxFields]
|
const otherFields = Object.keys(txFields).filter(k => !richFields.includes(k)) as [keyof TxFields]
|
||||||
|
const amountOptions = [
|
||||||
|
{ label: 'XRP', value: 'xrp' },
|
||||||
|
{ label: 'Token', value: 'token' }
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const defaultTokenAmount = {
|
||||||
|
value: '0',
|
||||||
|
currency: '',
|
||||||
|
issuer: ''
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
css={{
|
css={{
|
||||||
@@ -198,23 +225,106 @@ export const TxUI: FC<UIProps> = ({
|
|||||||
let _value = txFields[field]
|
let _value = txFields[field]
|
||||||
|
|
||||||
let value: string | undefined
|
let value: string | undefined
|
||||||
if (typeof _value === 'object') {
|
if (typeIs(_value, 'object')) {
|
||||||
if (_value.$type === 'json' && typeof _value.$value === 'object') {
|
if (_value.$type === 'json' && typeIs(_value.$value, ['object', 'array'])) {
|
||||||
value = JSON.stringify(_value.$value, null, 2)
|
value = JSON.stringify(_value.$value, null, 2)
|
||||||
} else {
|
} else {
|
||||||
value = _value.$value.toString()
|
value = _value.$value?.toString()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = _value?.toString()
|
value = _value?.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
const isXrp = typeof _value === 'object' && _value.$type === 'xrp'
|
const isXrpAmount = typeIs(_value, 'object') && _value.$type === 'amount.xrp'
|
||||||
|
const isTokenAmount = typeIs(_value, 'object') && _value.$type === 'amount.token'
|
||||||
const isJson = typeof _value === 'object' && _value.$type === 'json'
|
const isJson = typeof _value === 'object' && _value.$type === 'json'
|
||||||
const isFee = field === 'Fee'
|
const isFee = field === 'Fee'
|
||||||
let rows = isJson ? (value?.match(/\n/gm)?.length || 0) + 1 : undefined
|
let rows = isJson ? (value?.match(/\n/gm)?.length || 0) + 1 : undefined
|
||||||
if (rows && rows > 5) rows = 5
|
if (rows && rows > 5) rows = 5
|
||||||
|
let tokenAmount = defaultTokenAmount
|
||||||
|
if (isTokenAmount && typeIs(_value, 'object') && typeIs(_value.$value, 'object')) {
|
||||||
|
tokenAmount = {
|
||||||
|
value: _value.$value.value,
|
||||||
|
currency: _value.$value.currency,
|
||||||
|
issuer: _value.$value.issuer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isXrpAmount || isTokenAmount) {
|
||||||
|
return (
|
||||||
|
<TxField key={field} label={field}>
|
||||||
|
<Flex fluid css={{ alignItems: 'center' }}>
|
||||||
|
{isTokenAmount ? (
|
||||||
|
<Flex fluid row align="center" justify="space-between">
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
placeholder="Issuer"
|
||||||
|
value={tokenAmount.issuer}
|
||||||
|
onChange={e =>
|
||||||
|
setRawField(field, 'amount.token', {
|
||||||
|
...tokenAmount,
|
||||||
|
issuer: e.target.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
css={{ mx: '$1' }}
|
||||||
|
type="text"
|
||||||
|
value={tokenAmount.currency}
|
||||||
|
placeholder="Currency"
|
||||||
|
onChange={e => {
|
||||||
|
setRawField(field, 'amount.token', {
|
||||||
|
...tokenAmount,
|
||||||
|
currency: e.target.value
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
value={tokenAmount.value}
|
||||||
|
placeholder="Value"
|
||||||
|
onChange={e => {
|
||||||
|
setRawField(field, 'amount.token', {
|
||||||
|
...tokenAmount,
|
||||||
|
value: e.target.value
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
) : (
|
||||||
|
<Input
|
||||||
|
css={{ flex: 'inherit' }}
|
||||||
|
type="number"
|
||||||
|
value={value}
|
||||||
|
onChange={e => handleSetField(field, e.target.value)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Box
|
||||||
|
css={{
|
||||||
|
ml: '$2',
|
||||||
|
width: '150px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
instanceId="currency-type"
|
||||||
|
options={amountOptions}
|
||||||
|
value={isXrpAmount ? amountOptions['0'] : amountOptions['1']}
|
||||||
|
onChange={(e: any) => {
|
||||||
|
const opt = e as typeof amountOptions[number]
|
||||||
|
if (opt.value === 'xrp') {
|
||||||
|
setRawField(field, 'amount.xrp', '0')
|
||||||
|
} else {
|
||||||
|
setRawField(field, 'amount.token', defaultTokenAmount)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
</TxField>
|
||||||
|
)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<TxField key={field} label={field + (isXrp ? ' (XRP)' : '')}>
|
<TxField key={field} label={field}>
|
||||||
{isJson ? (
|
{isJson ? (
|
||||||
<Textarea
|
<Textarea
|
||||||
rows={rows}
|
rows={rows}
|
||||||
@@ -438,7 +548,7 @@ export const TxField: FC<{ label: string; children: ReactNode; multiLine?: boole
|
|||||||
justifyContent: 'flex-end',
|
justifyContent: 'flex-end',
|
||||||
alignItems: multiLine ? 'flex-start' : 'center',
|
alignItems: multiLine ? 'flex-start' : 'center',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
mb: '$3',
|
mb: '$2',
|
||||||
mt: '1px',
|
mt: '1px',
|
||||||
pr: '1px'
|
pr: '1px'
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -28,7 +28,11 @@
|
|||||||
"TransactionType": "CheckCash",
|
"TransactionType": "CheckCash",
|
||||||
"Amount": {
|
"Amount": {
|
||||||
"$value": "100",
|
"$value": "100",
|
||||||
"$type": "xrp"
|
"$type": "amount.xrp"
|
||||||
|
},
|
||||||
|
"DeliverMin": {
|
||||||
|
"$value": "",
|
||||||
|
"$type": "amount.xrp"
|
||||||
},
|
},
|
||||||
"CheckID": "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334",
|
"CheckID": "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334",
|
||||||
"Fee": "12"
|
"Fee": "12"
|
||||||
@@ -63,7 +67,7 @@
|
|||||||
"TransactionType": "EscrowCreate",
|
"TransactionType": "EscrowCreate",
|
||||||
"Amount": {
|
"Amount": {
|
||||||
"$value": "100",
|
"$value": "100",
|
||||||
"$type": "xrp"
|
"$type": "amount.xrp"
|
||||||
},
|
},
|
||||||
"Destination": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
"Destination": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||||
"CancelAfter": 533257958,
|
"CancelAfter": 533257958,
|
||||||
@@ -120,12 +124,11 @@
|
|||||||
"NFTokenID": "000100001E962F495F07A990F4ED55ACCFEEF365DBAA76B6A048C0A200000007",
|
"NFTokenID": "000100001E962F495F07A990F4ED55ACCFEEF365DBAA76B6A048C0A200000007",
|
||||||
"Amount": {
|
"Amount": {
|
||||||
"$value": "100",
|
"$value": "100",
|
||||||
"$type": "xrp"
|
"$type": "amount.xrp"
|
||||||
},
|
},
|
||||||
"Flags": "1",
|
"Flags": "1",
|
||||||
"Destination": "",
|
"Destination": "",
|
||||||
"Fee": "10",
|
"Fee": "10"
|
||||||
"Owner": ""
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"TransactionType": "OfferCancel",
|
"TransactionType": "OfferCancel",
|
||||||
@@ -143,10 +146,17 @@
|
|||||||
"Flags": "0",
|
"Flags": "0",
|
||||||
"LastLedgerSequence": 7108682,
|
"LastLedgerSequence": 7108682,
|
||||||
"Sequence": 8,
|
"Sequence": 8,
|
||||||
"TakerGets": "6000000",
|
"TakerGets": {
|
||||||
"Amount": {
|
"$type": "amount.xrp",
|
||||||
"$value": "100",
|
"$value": "6000000"
|
||||||
"$type": "xrp"
|
},
|
||||||
|
"TakerPays": {
|
||||||
|
"$type": "amount.token",
|
||||||
|
"$value": {
|
||||||
|
"currency": "GKO",
|
||||||
|
"issuer": "ruazs5h1qEsqpke88pcqnaseXdm6od2xc",
|
||||||
|
"value": "2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -155,7 +165,7 @@
|
|||||||
"Destination": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
|
"Destination": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
|
||||||
"Amount": {
|
"Amount": {
|
||||||
"$value": "100",
|
"$value": "100",
|
||||||
"$type": "xrp"
|
"$type": "amount.xrp"
|
||||||
},
|
},
|
||||||
"Fee": "12",
|
"Fee": "12",
|
||||||
"Flags": "2147483648",
|
"Flags": "2147483648",
|
||||||
@@ -166,7 +176,7 @@
|
|||||||
"TransactionType": "PaymentChannelCreate",
|
"TransactionType": "PaymentChannelCreate",
|
||||||
"Amount": {
|
"Amount": {
|
||||||
"$value": "100",
|
"$value": "100",
|
||||||
"$type": "xrp"
|
"$type": "amount.xrp"
|
||||||
},
|
},
|
||||||
"Destination": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
"Destination": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||||
"SettleDelay": 86400,
|
"SettleDelay": 86400,
|
||||||
@@ -182,7 +192,7 @@
|
|||||||
"Channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198",
|
"Channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198",
|
||||||
"Amount": {
|
"Amount": {
|
||||||
"$value": "200",
|
"$value": "200",
|
||||||
"$type": "xrp"
|
"$type": "amount.xrp"
|
||||||
},
|
},
|
||||||
"Expiration": 543171558,
|
"Expiration": 543171558,
|
||||||
"Fee": "10"
|
"Fee": "10"
|
||||||
@@ -238,7 +248,7 @@
|
|||||||
"Flags": "262144",
|
"Flags": "262144",
|
||||||
"LastLedgerSequence": 8007750,
|
"LastLedgerSequence": 8007750,
|
||||||
"LimitAmount": {
|
"LimitAmount": {
|
||||||
"$type": "json",
|
"$type": "amount.token",
|
||||||
"$value": {
|
"$value": {
|
||||||
"currency": "USD",
|
"currency": "USD",
|
||||||
"issuer": "rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc",
|
"issuer": "rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { showAlert } from '../state/actions/showAlert'
|
|||||||
import { parseJSON } from '../utils/json'
|
import { parseJSON } from '../utils/json'
|
||||||
import { extractFlags, getFlags } from './constants/flags'
|
import { extractFlags, getFlags } from './constants/flags'
|
||||||
import { fromHex } from '../utils/setHook'
|
import { fromHex } from '../utils/setHook'
|
||||||
|
import { typeIs } from '../utils/helpers'
|
||||||
|
|
||||||
export type SelectOption = {
|
export type SelectOption = {
|
||||||
value: string
|
value: string
|
||||||
@@ -136,31 +137,43 @@ export const prepareTransaction = (data: any) => {
|
|||||||
|
|
||||||
Object.keys(options).forEach(field => {
|
Object.keys(options).forEach(field => {
|
||||||
let _value = options[field]
|
let _value = options[field]
|
||||||
// convert xrp
|
if (!typeIs(_value, 'object')) return
|
||||||
if (_value && typeof _value === 'object' && _value.$type === 'xrp') {
|
// amount.xrp
|
||||||
if (+_value.$value) {
|
if (_value.$type === 'amount.xrp') {
|
||||||
options[field] = (+_value.$value * 1000000 + '') as any
|
if (_value.$value) {
|
||||||
|
options[field] = (+(_value as any).$value * 1000000 + '')
|
||||||
} else {
|
} else {
|
||||||
options[field] = undefined // 👇 💀
|
options[field] = undefined
|
||||||
}
|
|
||||||
}
|
|
||||||
// handle type: `json`
|
|
||||||
if (_value && typeof _value === 'object' && _value.$type === 'json') {
|
|
||||||
if (typeof _value.$value === 'object') {
|
|
||||||
options[field] = _value.$value
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
options[field] = JSON.parse(_value.$value)
|
|
||||||
} catch (error) {
|
|
||||||
const message = `Input error for json field '${field}': ${error instanceof Error ? error.message : ''
|
|
||||||
}`
|
|
||||||
console.error(message)
|
|
||||||
options[field] = _value.$value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete unnecessary fields
|
// amount.token
|
||||||
|
if (_value.$type === 'amount.token') {
|
||||||
|
if (typeIs(_value.$value, 'string')) {
|
||||||
|
options[field] = parseJSON(_value.$value)
|
||||||
|
} else if (typeIs(_value.$value, 'object')) {
|
||||||
|
options[field] = _value.$value
|
||||||
|
} else {
|
||||||
|
options[field] = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// json
|
||||||
|
if (_value.$type === 'json') {
|
||||||
|
const val = _value.$value;
|
||||||
|
let res: any = val;
|
||||||
|
if (typeIs(val, ["object", "array"])) {
|
||||||
|
options[field] = res
|
||||||
|
} else if (typeIs(val, "string") && (res = parseJSON(val))) {
|
||||||
|
options[field] = res;
|
||||||
|
} else {
|
||||||
|
options[field] = res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// delete unnecessary fields
|
||||||
|
Object.keys(options).forEach(field => {
|
||||||
if (!options[field]) {
|
if (!options[field]) {
|
||||||
delete options[field]
|
delete options[field]
|
||||||
}
|
}
|
||||||
@@ -254,16 +267,22 @@ export const prepareState = (value: string, transactionType?: string) => {
|
|||||||
Object.keys(rest).forEach(field => {
|
Object.keys(rest).forEach(field => {
|
||||||
const value = rest[field]
|
const value = rest[field]
|
||||||
const schemaVal = schema[field as keyof TxFields]
|
const schemaVal = schema[field as keyof TxFields]
|
||||||
const isXrp =
|
|
||||||
typeof value !== 'object' &&
|
const isAmount = schemaVal &&
|
||||||
schemaVal &&
|
typeIs(schemaVal, "object") &&
|
||||||
typeof schemaVal === 'object' &&
|
schemaVal.$type.startsWith('amount.');
|
||||||
schemaVal.$type === 'xrp'
|
|
||||||
if (isXrp) {
|
if (isAmount && ["number", "string"].includes(typeof value)) {
|
||||||
rest[field] = {
|
rest[field] = {
|
||||||
$type: 'xrp',
|
$type: 'amount.xrp', // Maybe have $type map or something
|
||||||
$value: +value / 1000000 // ! maybe use bigint?
|
$value: +value / 1000000 // ! maybe use bigint?
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (isAmount && typeof value === 'object') {
|
||||||
|
rest[field] = {
|
||||||
|
$type: 'amount.token',
|
||||||
|
$value: value
|
||||||
|
}
|
||||||
} else if (typeof value === 'object') {
|
} else if (typeof value === 'object') {
|
||||||
rest[field] = {
|
rest[field] = {
|
||||||
$type: 'json',
|
$type: 'json',
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ const estimateFee = async (
|
|||||||
const { signedTransaction } = sign(copyTx, keypair)
|
const { signedTransaction } = sign(copyTx, keypair)
|
||||||
|
|
||||||
const res = await xrplSend({ command: 'fee', tx_blob: signedTransaction })
|
const res = await xrplSend({ command: 'fee', tx_blob: signedTransaction })
|
||||||
|
if (res.error) {
|
||||||
|
throw new Error(`[${res.error}] ${res.error_exception}.`);
|
||||||
|
}
|
||||||
if (res && res.drops) {
|
if (res && res.drops) {
|
||||||
return res.drops
|
return res.drops
|
||||||
}
|
}
|
||||||
@@ -31,7 +34,8 @@ const estimateFee = async (
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!opts.silent) {
|
if (!opts.silent) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
toast.error('Cannot estimate fee.') // ? Some better msg
|
const msg = err instanceof Error ? err.message : 'Error estimating fee!';
|
||||||
|
toast.error(msg);
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,3 +19,17 @@ export const getFileExtention = (filename?: string): string | undefined => {
|
|||||||
const ext = (filename.includes('.') && filename.split('.').pop()) || undefined
|
const ext = (filename.includes('.') && filename.split('.').pop()) || undefined
|
||||||
return ext
|
return ext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Type = "array" | "undefined" | "object" | "string" | "number" | "bigint" | "boolean" | "symbol" | "function"
|
||||||
|
type obj = Record<string | number | symbol, unknown>
|
||||||
|
type arr = unknown[]
|
||||||
|
|
||||||
|
export const typeIs = <T extends Type>(arg: any, t: T | T[]): arg is unknown & (T extends "array" ? arr : T extends "undefined" ? undefined | null : T extends "object" ? obj : T extends "string" ? string : T extends "number" ? number : T extends "bigint" ? bigint : T extends "boolean" ? boolean : T extends "symbol" ? symbol : T extends "function" ? Function : never) => {
|
||||||
|
const types = Array.isArray(t) ? t : [t]
|
||||||
|
return types.includes(typeOf(arg) as T);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const typeOf = (arg: any): Type => {
|
||||||
|
const type = arg instanceof Array ? 'array' : arg === null ? 'undefined' : typeof arg
|
||||||
|
return type;
|
||||||
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
|
import { typeIs, typeOf } from './helpers'
|
||||||
|
|
||||||
export const extractSchemaProps = <O extends object>(obj: O) =>
|
export const extractSchemaProps = <O extends object>(obj: O) =>
|
||||||
Object.entries(obj).reduce((prev, [key, val]) => {
|
Object.entries(obj).reduce((prev, [key, val]) => {
|
||||||
const typeOf = <T>(arg: T) =>
|
const value = typeIs(val, "object") && '$type' in val && '$value' in val ? val?.$value : val
|
||||||
arg instanceof Array ? 'array' : arg === null ? 'undefined' : typeof arg
|
|
||||||
|
|
||||||
const value = typeOf(val) === 'object' && '$type' in val && '$value' in val ? val?.$value : val
|
|
||||||
const type = typeOf(value)
|
const type = typeOf(value)
|
||||||
|
|
||||||
let schema: any = {
|
let schema: any = {
|
||||||
@@ -12,19 +11,19 @@ export const extractSchemaProps = <O extends object>(obj: O) =>
|
|||||||
default: value
|
default: value
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeOf(value) === 'array') {
|
if (typeIs(value, "array")) {
|
||||||
const item = value[0] // TODO merge other item schema's into one
|
const item = value[0] // TODO merge other item schema's into one
|
||||||
if (typeOf(item) !== 'object') {
|
if (typeIs(item, "object")) {
|
||||||
schema.items = {
|
schema.items = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: extractSchemaProps(item),
|
properties: extractSchemaProps(item),
|
||||||
default: item
|
default: item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO support primitive-value arrays
|
// TODO primitive-value arrays
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeOf(value) === 'object') {
|
if (typeIs(value, "object")) {
|
||||||
schema.properties = extractSchemaProps(value)
|
schema.properties = extractSchemaProps(value)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user