lodash#castArray TypeScript Examples
The following examples show how to use
lodash#castArray.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: filter.helper.ts From typeorm-query-builder-wrapper with MIT License | 6 votes |
public notIn(exclude: string[] | number[] | string) {
if (typeof exclude === 'string') {
return this.completeWhere(
OPERATOR.SQL.OPERATOR_NOT_IN,
exclude,
{ quoteString: false },
);
}
if (isArray(exclude) && exclude.length === 0) {
throw new Error('Argument of NOT IN have to be non-empty array.')
}
// If comparing strings, must escape them as strings in the query.
this.escapeStringArray(castArray(exclude as string[]));
return this.completeWhere(
OPERATOR.SQL.OPERATOR_NOT_IN,
`(${exclude.join(', ')})`,
{ quoteString: false },
);
}
Example #2
Source File: multiple-columns-card.editor.tsx From next-basics with GNU General Public License v3.0 | 6 votes |
export function MultipleColumnsCardEditor({
nodeUid,
}: EditorComponentProps): React.ReactElement {
const node = useBuilderNode<MultipleColumnsCardProperties>({ nodeUid });
const { gridColumns } = node.$$parsedProperties;
const columns =
castArray(gridColumns).reduce((str, value) => {
if (typeof value === "string") {
str += `${value} `;
} else if (typeof value === "number") {
str += `${value}fr `;
}
return str;
}, "") || "1fr";
return (
<EditorContainer nodeUid={nodeUid}>
<div>
<SlotContainer
nodeUid={nodeUid}
slotName="content"
showOutlineIfEmpty
dropZoneBodyStyle={{ display: "grid", gridTemplateColumns: columns }}
slotContainerStyle={{ padding: "20px" }}
slotContentLayout={EditorSlotContentLayout.GRID}
/>
</div>
</EditorContainer>
);
}
Example #3
Source File: filter.helper.ts From typeorm-query-builder-wrapper with MIT License | 6 votes |
public in(include: string[] | number[] | string) {
if (typeof include === 'string') {
return this.completeWhere(
OPERATOR.SQL.OPERATOR_IN,
include,
{ quoteString: false },
);
}
if (isArray(include) && include.length === 0) {
throw new Error('Argument of IN have to be non-empty array.')
}
// If comparing strings, must escape them as strings in the query.
this.escapeStringArray(castArray(include as string[]));
return this.completeWhere(
OPERATOR.SQL.OPERATOR_IN,
`(${include.join(', ')})`,
{ quoteString: false },
);
}
Example #4
Source File: AccountsTask.ts From guardian with Apache License 2.0 | 6 votes |
async start<T extends BaseSubstrateGuardian>(guardian: T) {
const { apiRx } = await guardian.isReady();
const { account } = this.arguments;
return from(castArray(account)).pipe(
mergeMap((account) => apiRx.query.system.account(account).pipe(map(mapResult(account))))
);
}
Example #5
Source File: getProcessedEvents.ts From next-basics with GNU General Public License v3.0 | 6 votes |
export function processHandlers(
eventList: BrickEventHandler | BrickEventHandler[]
): BrickEventHandler[] {
const _processHandlers = (handler: BrickEventHandlerCallback): void => {
for (const [name, events] of Object.entries(handler)) {
const list = castArray(events);
handler[name as keyof BrickEventHandlerCallback] = list;
list.forEach((item) => {
if (item.callback) {
_processHandlers(item.callback);
}
});
}
};
const processedList = castArray(eventList);
processedList.forEach((handler) => {
if ((handler as UseProviderEventHandler).callback) {
_processHandlers((handler as UseProviderEventHandler).callback);
}
});
return processedList;
}
Example #6
Source File: conversation.request.ts From linkedin-private-api with MIT License | 6 votes |
getConversations({
recipients,
createdBefore,
}: {
recipients?: ProfileId | ProfileId[];
createdBefore?: Date;
}): Promise<GetConversationsResponse> {
const queryParams = {
keyVersion: 'LEGACY_INBOX',
...(recipients && { q: 'participants', recipients: castArray(recipients) }),
...(createdBefore && { createdBefore: createdBefore.getTime() }),
};
return this.request.get<GetConversationsResponse>('messaging/conversations', {
params: queryParams,
});
}
Example #7
Source File: PricesTask.ts From guardian with Apache License 2.0 | 6 votes |
async start<T extends BaseSubstrateGuardian>(guardian: T) {
const { apiRx } = await guardian.isReady();
const { key, period } = this.arguments;
if (key === 'all') {
return observeRPC<Vec<ITuple<[Codec, Option<TimestampedValue>]>>>(
apiRx.rpc.oracle.getAllValues,
['Aggregated'],
period
).pipe(
mergeMap((result): Observable<Price> => {
return from(result).pipe(
filter(([, item]) => item.isSome),
map(([key, item]) => ({
key: key.toString(),
value: getValueFromTimestampValue(item.unwrap()).toString()
}))
);
})
);
}
const keys = castArray(key).map((x) => apiRx.createType('CurrencyId', x));
return from(keys).pipe(
mergeMap((key) =>
from(getOraclePrice(apiRx, period)(key)).pipe(
map((price) => ({ key: key.toString(), value: price.toFixed(0) }))
)
),
filter((price) => price.value.length > 0)
);
}
Example #8
Source File: index.ts From excalideck with MIT License | 6 votes |
async expectToSee(...expectations: string[]) {
const stepTitle = [
"Expect to see:",
castArray(expectations)
.map((expectation) => `${expectation}`)
.join(", "),
].join(" ");
await test.step(stepTitle, async () => {
expect(await this.page.screenshot()).toMatchSnapshot(
this.issueNextSnapshotName()
);
});
}
Example #9
Source File: BalancesTask.ts From guardian with Apache License 2.0 | 6 votes |
async start<T extends BaseSubstrateGuardian>(guardian: T) {
const { apiRx } = await guardian.isReady();
const { account, currencyId } = this.arguments;
const currencyIds = castArray(currencyId).map((x) => apiRx.createType('CurrencyId', x));
const pairs = createAccountCurrencyIdPairs(account, currencyIds);
return from(pairs).pipe(mergeMap(({ account, currencyId }) => this.getBalance(apiRx, account, currencyId)));
}
Example #10
Source File: TraderInfoTask.ts From guardian with Apache License 2.0 | 6 votes |
getBalances = (apiRx: ApiRx) => (account: string, poolId: number | number[] | 'all') => {
return apiRx.query.marginProtocol.balances.entries(account).pipe(
mergeMap((entries) =>
entries.filter(([storageKey]) => {
if (poolId === 'all') return true;
const [, id] = storageKey.args;
return castArray(poolId).includes(id.toNumber());
})
)
);
}
Example #11
Source File: TraderInfoTask.ts From guardian with Apache License 2.0 | 6 votes |
async start(guardian: LaminarGuardian) {
const { apiRx } = await guardian.isReady();
const accounts = castArray(this.arguments.account);
const getBalances$ = getBalances(apiRx);
return from(accounts).pipe(
switchMap((account) => {
return getBalances$(account, this.arguments.poolId).pipe(
mergeMap(([storageKey, balance]) => {
const [account, poolId] = storageKey.args;
return getTraderState(apiRx, account, poolId, this.arguments.period).pipe(
map(
({
equity,
unrealized_pl: unrealizedPL,
margin_level: marginLevel,
margin_held: marginHeld,
free_margin: freeMargin
}) => {
return {
balance: balance.toString(),
freeMargin: freeMargin.toString(),
marginHeld: marginHeld.toString(),
unrealizedPl: unrealizedPL.toString(),
accumulatedSwap: equity.sub(new BN(balance)).sub(unrealizedPL).toString(),
equity: equity.toString(),
marginLevel: marginLevel.toString(),
totalLeveragedPosition: equity.mul(unit).div(marginLevel).toString()
};
}
)
);
})
);
})
);
}
Example #12
Source File: PositionsByTraderTask.ts From guardian with Apache License 2.0 | 6 votes |
async start(guardian: LaminarGuardian) {
const { apiRx } = await guardian.isReady();
const accounts = castArray(this.arguments.account);
const getSwap = accumulatedSwap(apiRx);
const getUnrealizedPL = unrealizedPL(apiRx);
return from(accounts).pipe(
switchMap((account) => apiRx.query.marginProtocol.positionsByTrader.entries(account)),
mergeAll(),
filter(([, value]) => !value.isEmpty),
mergeMap(([storageKey]) => {
const positionId = storageKey.args[1][1];
return apiRx.query.marginProtocol.positions(positionId).pipe(
filter((x) => x.isSome),
map((x) => x.unwrap()),
mergeMap((position) => combineLatest([of(position), getSwap(position), getUnrealizedPL(position)])),
map(([position, swap, profit]) => {
const { owner, poolId, pair, leverage, marginHeld } = position;
return {
account: owner.toString(),
liquidityPoolId: poolId.toString(),
positionId: positionId.toString(),
pair: {
base: pair.base.toString(),
quote: pair.quote.toString()
},
leverage: leverage.toString(),
marginHeld: marginHeld.toString(),
accumulatedSwap: swap ? swap.toFixed(0) : '',
profit: profit ? profit.toFixed(0) : ''
};
})
);
})
);
}
Example #13
Source File: test-generate.ts From prisma-nestjs-graphql with MIT License | 5 votes |
/**
* Get generator options after run prisma generate.
*/
async function createGeneratorOptions(
schema: string,
options?: string[] | string,
provider: 'postgresql' | 'mongodb' = 'postgresql',
): Promise<GeneratorOptions & { prismaClientDmmf: DMMF.Document }> {
const schemaHeader = `
datasource db {
provider = "${provider}"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
previewFeatures = ["filterJson", "fullTextSearch", "referentialIntegrity", "extendedIndexes", "fullTextIndex"]
}
`;
// eslint-disable-next-line prefer-rest-params
const hash = createHash(generatorVersion, schemaHeader, arguments);
const cacheFile = `${cachePath}/options-${hash}.js`;
if (!fs.existsSync(cacheFile)) {
const schemaFile = `${cachePath}/schema-${hash}.prisma`;
const schemaContent = `
${schemaHeader}
generator proxy {
provider = "node -r ts-node/register/transpile-only src/test/proxy-generator.ts"
output = "."
hash = "${hash}"
${castArray(options).join('\n')}
}
${schema}
`;
fs.writeFileSync(schemaFile, schemaContent);
await new Promise((resolve, reject) => {
const proc = exec(
`node node_modules/prisma/build/index.js generate --schema=${schemaFile}`,
);
if (!proc.stderr) {
throw new Error('Generate error');
}
proc.stdout?.pipe(process.stdout);
proc.stderr.on('data', data => {
reject(String(data));
});
proc.on('error', reject);
proc.on('exit', code => {
code === 0 ? resolve(0) : reject();
});
});
}
// eslint-disable-next-line unicorn/prefer-module
return require(cacheFile);
}
Example #14
Source File: PoolInfoTask.ts From guardian with Apache License 2.0 | 5 votes |
setup = async (apiRx: ApiRx, tokens: string[]) => {
const getPools = (poolId: number | number[] | 'all') => {
return apiRx.query.baseLiquidityPoolsForMargin.pools.entries().pipe(
mergeMap((entries) => {
return entries.filter(([storageKey]) => {
if (poolId === 'all') return true;
const [id] = storageKey.args;
return castArray(poolId).includes(id.toNumber());
});
})
);
};
const getTradingPairOptions = (poolId: LiquidityPoolId, getPairId: Function): Observable<TraderPairOptions[]> => {
return apiRx.query.marginLiquidityPools.poolTradingPairOptions.entries(poolId).pipe(
mergeMap((x) => x),
map(([storageKey, options]) => {
const [, tradingPair] = storageKey.args;
return apiRx.query.marginLiquidityPools.tradingPairOptions(tradingPair).pipe(
map((tradingPairOptions) => {
const maxSpread = tradingPairOptions.maxSpread;
let askSpread = options.askSpread.unwrapOrDefault();
let bidSpread = options.bidSpread.unwrapOrDefault();
if (maxSpread.isSome) {
askSpread = apiRx.createType('FixedU128', BN.max(maxSpread.unwrap(), askSpread));
bidSpread = apiRx.createType('FixedU128', BN.max(maxSpread.unwrap(), bidSpread));
}
return {
pair: {
base: tradingPair.base.toString(),
quote: tradingPair.quote.toString()
},
pairId: getPairId(tradingPair),
enabledTrades: options.enabledTrades.toJSON(),
askSpread: askSpread.toString(),
bidSpread: bidSpread.toString()
};
})
);
}),
combineLatestAll()
);
};
const getPairId = (pair: { base: string; quote: string }): string => {
const baseToken = tokens.find((x) => pair.base === x);
const quoteToken = tokens.find((x) => pair.quote === x);
return `${baseToken || pair.base}${quoteToken || pair.quote}`;
};
return { getPools, getTradingPairOptions, getPairId };
}
Example #15
Source File: LiquidityPoolTask.ts From guardian with Apache License 2.0 | 5 votes |
getSyntheticPools = (apiRx: ApiRx) => (poolId: number | number[] | 'all') => {
const upcomingPools$ = apiRx.query.baseLiquidityPoolsForSynthetic.nextPoolId().pipe(
pairwise(),
filter(([, next]) => !next.isZero()),
switchMap(([prev, next]) => range(prev.toNumber(), next.toNumber())),
distinctUntilChanged(),
mergeMap((poolId) =>
combineLatest([
of(poolId.toString()),
apiRx.query.baseLiquidityPoolsForSynthetic.pools(poolId).pipe(
filter((x) => x.isSome),
map((x) => x.unwrap())
)
])
)
);
if (poolId === 'all') {
return apiRx.query.baseLiquidityPoolsForSynthetic.pools.entries().pipe(
mergeMap((x) => x),
filter(([, value]) => value.isSome),
mergeMap(
([
{
args: [poolId]
},
pool
]) => combineLatest([of(poolId.toString()), of(pool.unwrap())])
),
concatWith(upcomingPools$)
);
} else {
return of(castArray(poolId)).pipe(
mergeMap((x) => x),
switchMap((poolId) =>
combineLatest([of(poolId.toString()), apiRx.query.baseLiquidityPoolsForSynthetic.pools(poolId)])
),
filter(([, pool]) => pool.isSome),
mergeMap(([poolId, value]) => combineLatest([of(poolId), of(value.unwrap())]))
);
}
}
Example #16
Source File: helpers.ts From guardian with Apache License 2.0 | 5 votes |
createAccountCurrencyIdPairs = <CurrencyId>(
account: string | string[],
currencyId: CurrencyId | CurrencyId[]
): { account: string; currencyId: CurrencyId }[] => {
return castArray(account).flatMap((account) => castArray(currencyId).map((currencyId) => ({ account, currencyId })));
}
Example #17
Source File: SyntheticPoolsTask.ts From guardian with Apache License 2.0 | 5 votes |
private getPoolIds(ethereumApi: EthereumApi, poolId: string | string[]) {
if (poolId === 'all') {
return ethereumApi.synthetic.allPoolIds().pipe(concatAll());
}
return from(castArray(poolId));
}
Example #18
Source File: PoolsTask.ts From guardian with Apache License 2.0 | 5 votes |
async start(guardian: AcalaGuardian) {
const { apiRx, getTokenPrecision } = await guardian.isReady();
const { currencyId } = this.arguments;
const stableCoin = apiRx.consts.cdpEngine.getStableCurrencyId;
const nativeCoin = apiRx.consts.currencies.getNativeCurrencyId;
let pairs: TradingPair[];
if (currencyId === 'all') {
const tradingPair = await lastValueFrom(apiRx.query.dex.liquidityPool.entries().pipe(take(1)));
pairs = tradingPair
.map(([key, value]) => {
const [balance1, balance2] = value;
if (balance1 && balance2) {
return key.args[0];
}
return undefined;
})
.filter((p): p is TradingPair => p !== undefined);
} else {
const currencies = castArray(currencyId);
pairs = currencies
.map((x) => apiRx.createType('CurrencyId', x))
.map((currencyId) => {
return currencyId.eq(nativeCoin)
? apiRx.createType('TradingPair', [currencyId, stableCoin])
: apiRx.createType('TradingPair', [stableCoin, currencyId]);
});
}
// ignore non-token currency
// TODO: support any currency
pairs = pairs.filter(([base, quote]) => {
return base.isToken && quote.isToken && !base.eq(quote);
});
return from(pairs).pipe(
mergeMap((pair) =>
apiRx.query.dex.liquidityPool(pair).pipe(
map(([base, other]) => {
const [baseCurrency, otherCurrency] = pair;
const basePrecision = getTokenPrecision(baseCurrency.asToken.toString());
assert(basePrecision);
const otherPrecision = getTokenPrecision(otherCurrency.asToken.toString());
assert(otherPrecision);
const _base = FixedPointNumber.fromInner(base.toString(), basePrecision);
const _other = FixedPointNumber.fromInner(other.toString(), otherPrecision);
const price = baseCurrency.eq(stableCoin) ? _base.div(_other) : _other.div(_base);
price.setPrecision(18);
return {
currencyId: pair.toString(),
price: price._getInner().toFixed(0),
baseLiquidity: base.toString(),
otherLiquidity: other.toString()
};
})
)
)
);
}
Example #19
Source File: CollateralAuctionsTask.ts From guardian with Apache License 2.0 | 5 votes |
async start(guardian: AcalaGuardian) {
const { apiRx } = await guardian.isReady();
const { account, currencyId } = this.arguments;
let currencies: CurrencyId[] = [];
const whitelist = apiRx.consts.cdpEngine.collateralCurrencyIds;
// make sure provided currency id is whitelisted
if (currencyId !== 'all') {
currencies = castArray(currencyId).map((x) => apiRx.createType('CurrencyId', x));
currencies.forEach((id) => {
if (!whitelist.find((x) => x.eq(id))) throw Error('Collateral currency id not allowed!');
});
} else {
currencies = whitelist;
}
const includesAccount = includesArgument<string>(account);
const includesCurrency = includesArgument<CurrencyId>(currencies);
const upcomingAuctions$ = apiRx.query.auction.auctionsIndex().pipe(
pairwise(),
filter(([, next]) => !next.isZero()),
switchMap(([prev, next]) => range(prev.toNumber(), next.toNumber())),
distinctUntilChanged(),
mergeMap((auctionId) => {
return combineLatest([
of(auctionId),
apiRx.query.auctionManager.collateralAuctions(auctionId),
apiRx.query.auction.auctions(auctionId)
]);
})
);
return apiRx.query.auctionManager.collateralAuctions.entries().pipe(
mergeMap((entry) => entry),
mergeMap((entry) => {
const [storageKey, maybecollateralAuction] = entry;
const [auctionId] = storageKey.args;
return combineLatest([of(auctionId), of(maybecollateralAuction), apiRx.query.auction.auctions(auctionId)]);
}),
concatWith(upcomingAuctions$),
filter(([, maybecollateralAuction, maybeAuction]) => {
if (maybecollateralAuction.isNone) return false;
if (maybeAuction.isNone) return false;
const { refundRecipient, currencyId } = maybecollateralAuction.unwrap();
if (!includesAccount(refundRecipient.toString())) return false;
if (!includesCurrency(currencyId)) return false;
return true;
}),
map(([auctionId, maybecollateralAuction, maybeAuction]) => {
const collateralAuction = maybecollateralAuction.unwrap();
const auction = maybeAuction.unwrap();
const [lastBidder, lastBid] = auction.bid.isSome ? auction.bid.unwrap() : [];
return {
account: collateralAuction.refundRecipient.toString(),
currencyId: collateralAuction.currencyId.asToken.toString(),
auctionId: Number(auctionId.toString()),
initialAmount: collateralAuction.initialAmount.toString(),
amount: collateralAuction.amount.toString(),
target: collateralAuction.target.toString(),
startTime: Number(collateralAuction.startTime.toString()),
endTime: auction.end.isSome ? Number(auction.end.toString()) : undefined,
lastBidder: lastBidder && lastBidder.toString(),
lastBid: lastBid && lastBid.toString()
};
}),
drr()
);
}
Example #20
Source File: paramsSerializer.ts From linkedin-private-api with MIT License | 5 votes |
encodeFilter = (value: string | string[], key: string) => encodeURIComponent(`${key}->${castArray(value).join('|')}`)
Example #21
Source File: LoansTask.ts From guardian with Apache License 2.0 | 4 votes |
async start(guardian: AcalaGuardian) {
const { apiRx, getTokenPrecision } = await guardian.isReady();
const { account, currencyId } = this.arguments;
const stableCoin = apiRx.consts.cdpEngine.getStableCurrencyId;
const stableCoinPrice = apiRx.consts.prices.stableCurrencyFixedPrice;
const collateralCurrencyIds = apiRx.consts.cdpEngine.collateralCurrencyIds;
let currencyIds: CurrencyId[];
if (currencyId === 'all') {
currencyIds = apiRx.createType<Vec<CurrencyId>>('Vec<CurrencyId>', collateralCurrencyIds);
} else {
currencyIds = castArray(currencyId).map((x) => apiRx.createType('CurrencyId', x));
}
// ignore non-token collaterals
// TODO: support any currency
currencyIds = currencyIds.filter((x) => x.isToken);
// create {account, currencyId} paris
const pairs = createAccountCurrencyIdPairs<CurrencyId>(account, currencyIds);
const oraclePrice = getOraclePrice(apiRx);
return from(pairs).pipe(
mergeMap(({ currencyId, account }) =>
apiRx.query.loans.positions(currencyId, account).pipe(
mergeMap((position) => combineLatest([of(position), apiRx.query.cdpEngine.debitExchangeRate(currencyId)])),
mergeMap(([position, debitExchangeRate]) => {
const exchangeRate = debitExchangeRate.isSome
? debitExchangeRate.unwrap()
: apiRx.consts.cdpEngine.defaultDebitExchangeRate;
return combineLatest([of(position), of(exchangeRate), oraclePrice(currencyId)]);
}),
filter(([position, exchangeRate, collateralPrice]) => {
const stableCoinPrecision = getTokenPrecision(stableCoin.asToken.toString());
const collateralPrecision = getTokenPrecision(currencyId.asToken.toString());
const collateral = FixedPointNumber.fromInner(position.collateral.toString(), collateralPrecision);
const collateralUSD = FixedPointNumber.fromInner(collateralPrice).times(collateral);
const debit = FixedPointNumber.fromInner(position.debit.toString(), stableCoinPrecision);
if (debit.isZero()) return false;
const debitsUSD = debit
.times(FixedPointNumber.fromInner(exchangeRate.toString()))
.times(FixedPointNumber.fromInner(stableCoinPrice.toString()));
const collateralRatio = collateralUSD.div(debitsUSD);
if (collateralRatio.isNaN()) return false;
return true;
}),
map(([position, exchangeRate, collateralPrice]) => {
const stableCoinPrecision = getTokenPrecision(stableCoin.asToken.toString());
assert(stableCoinPrecision);
const collateralPrecision = getTokenPrecision(currencyId.asToken.toString());
assert(collateralPrecision);
const collateral = FixedPointNumber.fromInner(position.collateral.toString(), collateralPrecision);
const collateralUSD = FixedPointNumber.fromInner(collateralPrice).times(collateral);
const debit = FixedPointNumber.fromInner(position.debit.toString(), stableCoinPrecision);
const debitsUSD = debit
.times(FixedPointNumber.fromInner(exchangeRate.toString()))
.times(FixedPointNumber.fromInner(stableCoinPrice.toString()));
const collateralRatio = collateralUSD.div(debitsUSD);
// set precision back stable coin
debitsUSD.setPrecision(stableCoinPrecision);
return {
account,
currencyId: currencyId.toString(),
debits: position.debit.toString(),
debitsUSD: debitsUSD._getInner().toFixed(0),
collaterals: position.collateral.toString(),
collateralRatio: collateralRatio.toString()
};
})
)
)
);
}
Example #22
Source File: covertFormValueToEvent.ts From next-basics with GNU General Public License v3.0 | 4 votes |
export function covertFormValueToEvent(
formValue: EventFormField
): BrickEventHandler {
if (formValue.handlerType === HandlerType.BuiltinAction) {
//特殊处理 history.push / segueId.push
if (["segue.push", "history.push"].includes(formValue.action)) {
const restArgs =
formValue.args !== undefined
? safeLoadField(formValue.args, "args")
: [];
return {
action: formValue.action as string,
...safeLoadFields({
if: formValue.if,
callback: formValue.callback,
}),
args: [
formValue.action === "segue.push"
? formValue.segueId
: formValue.path,
...(isNil(restArgs) ? [] : castArray(restArgs)),
],
} as BuiltinBrickEventHandler;
}
return {
action: formValue.action,
...safeLoadFields({
if: formValue.if,
args: formValue.args,
callback: formValue.callback,
}),
} as BuiltinBrickEventHandler;
} else if (formValue.handlerType === HandlerType.UseProvider) {
const useProvider =
formValue.providerType === "provider"
? formValue.provider
: formValue.flow;
const loadFields = safeLoadFields({
if: formValue.if,
args: formValue.args,
poll: formValue.poll,
callback: formValue.callback,
});
if (loadFields.poll && formValue.pollEnabled) {
set(loadFields, "poll.enabled", formValue.pollEnabled);
}
return {
useProvider,
...(formValue.useProviderMethod === "resolve"
? {}
: { method: formValue.useProviderMethod }),
...loadFields,
} as UseProviderEventHandler;
} else if (
formValue.handlerType === HandlerType.CustomBrick &&
formValue.brickEventType === CustomBrickEventType.ExecuteMethod
) {
return {
...(formValue.selectorType === "target"
? { target: formValue.brickSelector }
: { targetRef: formValue.brickSelector }),
method: formValue.method,
...safeLoadFields({
if: formValue.if,
args: formValue.args,
callback: formValue.callback,
}),
} as ExecuteCustomBrickEventHandler;
} else if (
formValue.handlerType === HandlerType.CustomBrick &&
formValue.brickEventType === CustomBrickEventType.SetProps
) {
return {
...(formValue.selectorType === "target"
? { target: formValue.brickSelector }
: { targetRef: formValue.brickSelector }),
...safeLoadFields({
if: formValue.if,
properties: formValue.properties,
}),
} as SetPropsCustomBrickEventHandler;
}
}
Example #23
Source File: input-type.ts From prisma-nestjs-graphql with MIT License | 4 votes |
export function inputType(
args: EventArguments & {
inputType: InputType;
fileType: string;
classDecoratorName: string;
},
) {
const {
classDecoratorName,
classTransformerTypeModels,
config,
eventEmitter,
fieldSettings,
fileType,
getModelName,
getSourceFile,
inputType,
models,
removeTypes,
typeNames,
} = args;
typeNames.add(inputType.name);
const importDeclarations = new ImportDeclarationMap();
const sourceFile = getSourceFile({
name: inputType.name,
type: fileType,
});
const classStructure: ClassDeclarationStructure = {
kind: StructureKind.Class,
isExported: true,
name: inputType.name,
decorators: [
{
name: classDecoratorName,
arguments: [],
},
],
properties: [],
};
const modelName = getModelName(inputType.name) || '';
const model = models.get(modelName);
const modelFieldSettings = model && fieldSettings.get(model.name);
const moduleSpecifier = '@nestjs/graphql';
// console.log('sourceFile.getBaseName()', sourceFile.getBaseName());
importDeclarations
.set('Field', {
namedImports: [{ name: 'Field' }],
moduleSpecifier,
})
.set(classDecoratorName, {
namedImports: [{ name: classDecoratorName }],
moduleSpecifier,
});
const useInputType = config.useInputType.find(x =>
inputType.name.includes(x.typeName),
);
for (const field of inputType.fields) {
field.inputTypes = field.inputTypes.filter(t => !removeTypes.has(String(t.type)));
eventEmitter.emitSync('BeforeGenerateField', field, args);
const { inputTypes, isRequired, name } = field;
if (inputTypes.length === 0) {
// No types
continue;
}
const usePattern = useInputType?.ALL || useInputType?.[name];
const graphqlInputType = getGraphqlInputType(inputTypes, usePattern);
const { isList, location, type } = graphqlInputType;
const typeName = String(type);
const settings = modelFieldSettings?.get(name);
const propertySettings = settings?.getPropertyType({
name: inputType.name,
input: true,
});
const modelField = model?.fields.find(f => f.name === name);
const isCustomsApplicable = typeName === modelField?.type;
const propertyType = castArray(
propertySettings?.name ||
getPropertyType({
location,
type: typeName,
}),
);
const property = propertyStructure({
name,
isNullable: !isRequired,
propertyType,
isList,
});
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
classStructure.properties!.push(property);
if (propertySettings) {
importDeclarations.create({ ...propertySettings });
} else if (propertyType.includes('Decimal')) {
importDeclarations.add('Decimal', '@prisma/client/runtime');
}
// Get graphql type
let graphqlType: string;
const shouldHideField =
settings?.shouldHideField({
name: inputType.name,
input: true,
}) ||
config.decorate.some(
d =>
d.name === 'HideField' &&
d.from === '@nestjs/graphql' &&
d.isMatchField(name) &&
d.isMatchType(inputType.name),
);
const fieldType = settings?.getFieldType({
name: inputType.name,
input: true,
});
if (fieldType && isCustomsApplicable && !shouldHideField) {
graphqlType = fieldType.name;
importDeclarations.create({ ...fieldType });
} else {
// Import property type class
const graphqlImport = getGraphqlImport({
config,
sourceFile,
location,
typeName,
getSourceFile,
});
graphqlType = graphqlImport.name;
let referenceName = propertyType[0];
if (location === 'enumTypes') {
referenceName = last(referenceName.split(' ')) as string;
}
if (
graphqlImport.specifier &&
!importDeclarations.has(graphqlImport.name) &&
graphqlImport.name !== inputType.name
// ((graphqlImport.name !== inputType.name && !shouldHideField) ||
// (shouldHideField && referenceName === graphqlImport.name))
) {
importDeclarations.set(graphqlImport.name, {
namedImports: [{ name: graphqlImport.name }],
moduleSpecifier: graphqlImport.specifier,
});
}
}
ok(property.decorators, 'property.decorators is undefined');
if (shouldHideField) {
importDeclarations.add('HideField', '@nestjs/graphql');
property.decorators.push({ name: 'HideField', arguments: [] });
} else {
// Generate `@Field()` decorator
property.decorators.push({
name: 'Field',
arguments: [
isList ? `() => [${graphqlType}]` : `() => ${graphqlType}`,
JSON5.stringify({
...settings?.fieldArguments(),
nullable: !isRequired,
}),
],
});
// Debug
// if (classStructure.name === 'XCreateInput') {
// console.log({
// field,
// property,
// modelField,
// graphqlInputType,
// 'args.inputType': args.inputType,
// 'classStructure.name': classStructure.name,
// classTransformerTypeModels,
// modelName,
// graphqlType,
// });
// }
if (graphqlType === 'GraphQLDecimal') {
importDeclarations.add('transformToDecimal', 'prisma-graphql-type-decimal');
importDeclarations.add('Transform', 'class-transformer');
importDeclarations.add('Type', 'class-transformer');
property.decorators.push(
{
name: 'Type',
arguments: ['() => Object'],
},
{
name: 'Transform',
arguments: ['transformToDecimal'],
},
);
} else if (
location === 'inputObjectTypes' &&
(modelField?.type === 'Decimal' ||
[
'connect',
'connectOrCreate',
'create',
'createMany',
'data',
'delete',
'deleteMany',
'disconnect',
'set',
'update',
'updateMany',
'upsert',
'where',
].includes(name) ||
classTransformerTypeModels.has(getModelName(graphqlType) || ''))
) {
importDeclarations.add('Type', 'class-transformer');
property.decorators.push({ name: 'Type', arguments: [`() => ${graphqlType}`] });
}
if (isCustomsApplicable) {
for (const options of settings || []) {
if (
(options.kind === 'Decorator' && options.input && options.match?.(name)) ??
true
) {
property.decorators.push({
name: options.name,
arguments: options.arguments as string[],
});
ok(options.from, "Missed 'from' part in configuration or field setting");
importDeclarations.create(options);
}
}
}
for (const decorate of config.decorate) {
if (decorate.isMatchField(name) && decorate.isMatchType(inputType.name)) {
property.decorators.push({
name: decorate.name,
arguments: decorate.arguments?.map(x => pupa(x, { propertyType })),
});
importDeclarations.create(decorate);
}
}
}
eventEmitter.emitSync('ClassProperty', property, {
location,
isList,
propertyType,
});
}
sourceFile.set({
statements: [...importDeclarations.toStatements(), classStructure],
});
}
Example #24
Source File: model-output-type.ts From prisma-nestjs-graphql with MIT License | 4 votes |
export function modelOutputType(outputType: OutputType, args: EventArguments) {
const { getSourceFile, models, config, modelFields, fieldSettings, eventEmitter } =
args;
const model = models.get(outputType.name);
ok(model, `Cannot find model by name ${outputType.name}`);
const sourceFile = getSourceFile({
name: outputType.name,
type: 'model',
});
const sourceFileStructure = sourceFile.getStructure();
const exportDeclaration = getExportDeclaration(
model.name,
sourceFileStructure.statements as StatementStructures[],
);
const importDeclarations = new ImportDeclarationMap();
const classStructure: ClassDeclarationStructure = {
kind: StructureKind.Class,
isExported: true,
name: outputType.name,
decorators: [
{
name: 'ObjectType',
arguments: [],
},
],
properties: [],
};
(sourceFileStructure.statements as StatementStructures[]).push(classStructure);
ok(classStructure.decorators, 'classStructure.decorators is undefined');
const decorator = classStructure.decorators.find(d => d.name === 'ObjectType');
ok(decorator, 'ObjectType decorator not found');
let modelSettings: ObjectSettings | undefined;
// Get model settings from documentation
if (model.documentation) {
const objectTypeOptions: PlainObject = {};
const { documentation, settings } = createObjectSettings({
text: model.documentation,
config,
});
if (documentation) {
if (!classStructure.leadingTrivia) {
classStructure.leadingTrivia = createComment(documentation);
}
objectTypeOptions.description = documentation;
}
decorator.arguments = settings.getObjectTypeArguments(objectTypeOptions);
modelSettings = settings;
}
importDeclarations.add('Field', nestjsGraphql);
importDeclarations.add('ObjectType', nestjsGraphql);
for (const field of outputType.fields) {
let fileType = 'model';
const { location, isList, type, namespace } = field.outputType;
let outputTypeName = String(type);
if (namespace !== 'model') {
fileType = 'output';
outputTypeName = getOutputTypeName(outputTypeName);
}
const modelField = modelFields.get(model.name)?.get(field.name);
const settings = fieldSettings.get(model.name)?.get(field.name);
const fieldType = settings?.getFieldType({
name: outputType.name,
output: true,
});
const propertySettings = settings?.getPropertyType({
name: outputType.name,
output: true,
});
const propertyType = castArray(
propertySettings?.name ||
getPropertyType({
location,
type: outputTypeName,
}),
);
// For model we keep only one type
propertyType.splice(1, propertyType.length);
if (field.isNullable && !isList) {
propertyType.push('null');
}
let graphqlType: string;
if (fieldType) {
graphqlType = fieldType.name;
importDeclarations.create({ ...fieldType });
} else {
const graphqlImport = getGraphqlImport({
config,
sourceFile,
fileType,
location,
isId: modelField?.isId,
noTypeId: config.noTypeId,
typeName: outputTypeName,
getSourceFile,
});
graphqlType = graphqlImport.name;
if (graphqlImport.name !== outputType.name && graphqlImport.specifier) {
importDeclarations.add(graphqlImport.name, graphqlImport.specifier);
}
}
const property = propertyStructure({
name: field.name,
isNullable: field.isNullable,
hasExclamationToken: true,
hasQuestionToken: location === 'outputObjectTypes',
propertyType,
isList,
});
if (typeof property.leadingTrivia === 'string' && modelField?.documentation) {
property.leadingTrivia += createComment(modelField.documentation, settings);
}
classStructure.properties?.push(property);
if (propertySettings) {
importDeclarations.create({ ...propertySettings });
} else if (propertyType.includes('Decimal')) {
importDeclarations.add('Decimal', '@prisma/client/runtime');
}
ok(property.decorators, 'property.decorators is undefined');
if (settings?.shouldHideField({ name: outputType.name, output: true })) {
importDeclarations.add('HideField', nestjsGraphql);
property.decorators.push({ name: 'HideField', arguments: [] });
} else {
// Generate `@Field()` decorator
property.decorators.push({
name: 'Field',
arguments: [
isList ? `() => [${graphqlType}]` : `() => ${graphqlType}`,
JSON5.stringify({
...settings?.fieldArguments(),
nullable: Boolean(field.isNullable),
defaultValue: ['number', 'string', 'boolean'].includes(
typeof modelField?.default,
)
? modelField?.default
: undefined,
description: modelField?.documentation,
}),
],
});
for (const setting of settings || []) {
if (shouldBeDecorated(setting) && (setting.match?.(field.name) ?? true)) {
property.decorators.push({
name: setting.name,
arguments: setting.arguments as string[],
});
ok(setting.from, "Missed 'from' part in configuration or field setting");
importDeclarations.create(setting);
}
}
for (const decorate of config.decorate) {
if (decorate.isMatchField(field.name) && decorate.isMatchType(outputTypeName)) {
property.decorators.push({
name: decorate.name,
arguments: decorate.arguments?.map(x => pupa(x, { propertyType })),
});
importDeclarations.create(decorate);
}
}
}
eventEmitter.emitSync('ClassProperty', property, {
location,
isList,
propertyType,
});
}
// Generate class decorators from model settings
for (const setting of modelSettings || []) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
if (shouldBeDecorated(setting)) {
classStructure.decorators.push({
name: setting.name,
arguments: setting.arguments as string[],
});
importDeclarations.create(setting);
}
}
if (exportDeclaration) {
sourceFile.set({
statements: [exportDeclaration, '\n', classStructure],
});
const classDeclaration = sourceFile.getClassOrThrow(model.name);
const commentedText = classDeclaration
.getText()
.split('\n')
.map(x => `// ${x}`);
classDeclaration.remove();
sourceFile.addStatements(['\n', ...commentedText]);
} else {
sourceFile.set({
statements: [...importDeclarations.toStatements(), classStructure],
});
}
}
Example #25
Source File: output-type.ts From prisma-nestjs-graphql with MIT License | 4 votes |
export function outputType(outputType: OutputType, args: EventArguments) {
const { getSourceFile, models, eventEmitter, fieldSettings, getModelName, config } =
args;
const importDeclarations = new ImportDeclarationMap();
const fileType = 'output';
const modelName = getModelName(outputType.name) || '';
const model = models.get(modelName);
const isAggregateOutput =
model &&
/(?:Count|Avg|Sum|Min|Max)AggregateOutputType$/.test(outputType.name) &&
String(outputType.name).startsWith(model.name);
const isCountOutput =
model?.name && outputType.name === `${model.name}CountOutputType`;
// Get rid of bogus suffixes
outputType.name = getOutputTypeName(outputType.name);
if (isAggregateOutput) {
eventEmitter.emitSync('AggregateOutput', { ...args, outputType });
}
const sourceFile = getSourceFile({
name: outputType.name,
type: fileType,
});
const classStructure: ClassDeclarationStructure = {
kind: StructureKind.Class,
isExported: true,
name: outputType.name,
decorators: [
{
name: 'ObjectType',
arguments: [],
},
],
properties: [],
};
importDeclarations.add('Field', nestjsGraphql);
importDeclarations.add('ObjectType', nestjsGraphql);
for (const field of outputType.fields) {
const { location, isList, type } = field.outputType;
const outputTypeName = getOutputTypeName(String(type));
const settings = isCountOutput
? undefined
: model && fieldSettings.get(model.name)?.get(field.name);
const propertySettings = settings?.getPropertyType({
name: outputType.name,
output: true,
});
const isCustomsApplicable =
outputTypeName === model?.fields.find(f => f.name === field.name)?.type;
field.outputType.type = outputTypeName;
const propertyType = castArray(
propertySettings?.name ||
getPropertyType({
location,
type: outputTypeName,
}),
);
const property = propertyStructure({
name: field.name,
isNullable: field.isNullable,
hasQuestionToken: isCountOutput ? true : undefined,
propertyType,
isList,
});
classStructure.properties?.push(property);
if (propertySettings) {
importDeclarations.create({ ...propertySettings });
} else if (propertyType.includes('Decimal')) {
importDeclarations.add('Decimal', '@prisma/client/runtime');
}
// Get graphql type
let graphqlType: string;
const shouldHideField =
settings?.shouldHideField({
name: outputType.name,
output: true,
}) ||
config.decorate.some(
d =>
d.name === 'HideField' &&
d.from === '@nestjs/graphql' &&
d.isMatchField(field.name) &&
d.isMatchType(outputTypeName),
);
const fieldType = settings?.getFieldType({
name: outputType.name,
output: true,
});
if (fieldType && isCustomsApplicable && !shouldHideField) {
graphqlType = fieldType.name;
importDeclarations.create({ ...fieldType });
} else {
const graphqlImport = getGraphqlImport({
config,
sourceFile,
fileType,
location,
isId: false,
typeName: outputTypeName,
getSourceFile,
});
graphqlType = graphqlImport.name;
let referenceName = propertyType[0];
if (location === 'enumTypes') {
referenceName = last(referenceName.split(' ')) as string;
}
if (
graphqlImport.specifier &&
!importDeclarations.has(graphqlImport.name) &&
((graphqlImport.name !== outputType.name && !shouldHideField) ||
(shouldHideField && referenceName === graphqlImport.name))
) {
importDeclarations.set(graphqlImport.name, {
namedImports: [{ name: graphqlImport.name }],
moduleSpecifier: graphqlImport.specifier,
});
}
}
ok(property.decorators, 'property.decorators is undefined');
if (shouldHideField) {
importDeclarations.add('HideField', nestjsGraphql);
property.decorators.push({ name: 'HideField', arguments: [] });
} else {
// Generate `@Field()` decorator
property.decorators.push({
name: 'Field',
arguments: [
isList ? `() => [${graphqlType}]` : `() => ${graphqlType}`,
JSON5.stringify({
...settings?.fieldArguments(),
nullable: Boolean(field.isNullable),
}),
],
});
if (isCustomsApplicable) {
for (const options of settings || []) {
if (
(options.kind === 'Decorator' &&
options.output &&
options.match?.(field.name)) ??
true
) {
property.decorators.push({
name: options.name,
arguments: options.arguments as string[],
});
ok(options.from, "Missed 'from' part in configuration or field setting");
importDeclarations.create(options);
}
}
}
}
eventEmitter.emitSync('ClassProperty', property, {
location,
isList,
propertyType,
});
}
sourceFile.set({
statements: [...importDeclarations.toStatements(), classStructure],
});
}
Example #26
Source File: CmdbInstanceSelect.tsx From next-basics with GNU General Public License v3.0 | 4 votes |
export function CmdbInstanceSelectItem(
props: CmdbInstanceSelectProps,
ref: any
): React.ReactElement {
const {
showKeyField,
// 默认显示 label 为模型的 name/hostname, value 为 instanceId
// 当showKeyField时,实例展示是用showKey里的数据展示
fields = {
label: [showKeyField ? "#showKey" : getInstanceNameKey(props.objectId)],
value: "instanceId",
},
minimumInputLength = 0,
extraSearchKey = [],
extraFields = [],
mode,
placeholder,
allowClear,
pageSize,
showSearchTip,
permission,
ignoreMissingFieldError,
} = props;
const userQuery = formatUserQuery(props.instanceQuery);
//istanbul ignore else
if (!fields.value) {
fields.value = "instanceId";
}
const [value, setValue] = React.useState();
const [options, setOptions] = React.useState<ComplexOption[]>([]);
const [selectedOptions, setSelectedOptions] = React.useState<ComplexOption[]>(
[]
);
const [total, setTotal] = React.useState(0);
const [loading, setLoading] = React.useState(false);
const computeFields = () => {
const result = [
fields.value,
...(Array.isArray(fields.label) ? fields.label : [fields.label]),
...extraSearchKey,
...extraFields,
];
if (props.objectId === "USER") {
result.push("user_icon");
}
return result;
};
const handleChange = (newValue: any): void => {
let selected: any | any[];
if (mode === "multiple") {
const valueSet = new Set(newValue);
selected = options.filter((item) => valueSet.has(item.value));
const oldValueSet = new Set(
difference(
newValue,
selected.map((item) => item.value)
)
);
selected = selected.concat(
selectedOptions.filter((item) => oldValueSet.has(item.value))
);
} else {
selected = options.find((item) => item.value === newValue);
}
setValue(newValue);
setSelectedOptions(selected);
props.onChange && props.onChange(newValue, selected);
};
//istanbul ignore else
const handleSearch = async (
q: string,
extraQuery: any,
forceSearch = false,
pageSizeQuery?: number
): Promise<ComplexOption[]> => {
if (forceSearch || q.length >= minimumInputLength) {
try {
let list = [];
if (!props.objectId) {
return;
}
setLoading(true);
const fieldsQuery = Array.isArray(fields.label)
? fields.label.map((label) => ({ [label]: { $like: `%${q}%` } }))
: [{ [fields.label]: { $like: `%${q}%` } }];
const data = await InstanceApi_postSearchV3(props.objectId, {
query: {
$and: [
{
$or: [
...fieldsQuery,
...extraSearchKey.map((key) => ({
[key]: { $like: `%${q}%` },
})),
],
},
...extraQuery,
],
},
...(permission ? { permission } : {}),
fields: computeFields(),
page_size: pageSizeQuery || pageSize,
ignore_missing_field_error: ignoreMissingFieldError,
});
list = data.list;
setTotal(data.total);
// 根据用户设置路径显示特定的 label 和 value
const option = list.map((item) => ({
...item,
label: Array.isArray(fields.label)
? fields.label.map((label) => get(item, label))
: get(item, fields.label),
value: get(item, fields.value),
...(props.objectId === "USER"
? {
user_icon: get(item, "user_icon", "defaultIcon"),
}
: {}),
}));
setOptions(option);
return option;
} catch (e) {
handleHttpError(e);
} finally {
setLoading(false);
}
}
};
const fetchInstanceData = async (): Promise<void> => {
await handleSearch("", userQuery);
};
const getLabelOptions = (op: any) => {
if (props.labelTemplate) {
return parseTemplate(props.labelTemplate, op);
} else {
const label = op.label;
if (Array.isArray(label)) {
const firstKey = label[0];
const resKey = label.slice(1, label.length).join(",");
if (Array.isArray(firstKey) && props.showKeyField) {
const subFirstKey = firstKey[0];
const subResKey = firstKey.slice(1, firstKey.length).join(",");
return subResKey && props.isMultiLabel
? `${subFirstKey}(${subResKey})`
: subFirstKey ?? "";
}
return resKey && props.isMultiLabel
? `${firstKey}(${resKey})`
: firstKey ?? "";
} else {
return label;
}
}
};
React.useEffect(() => {
// 初始化时通过用户的 value 得出首次 label 的值
// 由于value的不确定性,可能存在首次查询的值不唯一,初始化时也添加instanceQuery
(async () => {
if (!isEqual(props.value, value) && props.value !== undefined) {
const option = await handleSearch(
"",
[
{
[fields.value || "instanceId"]: {
$in: castArray(props.value),
},
},
...userQuery,
],
true,
props.value?.length >= pageSize ? props.value.length : pageSize
);
setSelectedOptions(option);
}
setValue(props.value);
})();
}, [props.value]);
React.useEffect(() => {
if (!props.firstRender) {
const resetVal: [] | "" = mode === "multiple" ? [] : "";
setValue(resetVal);
}
}, [props.objectId]);
//istanbul ignore else
const debounceSearch = debounce(
(q: string) => handleSearch(q, userQuery),
500
);
return (
<Spin spinning={loading}>
<Select
ref={ref}
allowClear={allowClear}
style={defaults(props.inputBoxStyle, { width: "100%" })}
showSearch
filterOption={false}
value={value}
mode={mode as ModeOption}
placeholder={
placeholder || i18n.t(`${NS_FORMS}:${K.BACKGROUND_SEARCH}`)
}
onChange={handleChange}
onSearch={debounceSearch}
onFocus={fetchInstanceData}
optionLabelProp="label"
disabled={props.disabled}
dropdownRender={(menu) => {
return (
<div>
{menu}
{showSearchTip && total > pageSize && (
<div className={style.moreChoices}>
仅显示前{pageSize}项,更多结果请搜索
</div>
)}
</div>
);
}}
{...(props.popoverPositionType === "parent"
? { getPopupContainer: (triggerNode) => triggerNode.parentElement }
: {})}
>
{options.map((op, index) => {
const optionLabel = getLabelOptions(op);
return (
<Select.Option key={index} value={op.value} label={optionLabel}>
{props.showTooltip ? (
<Tooltip title={optionLabel}>
{op.user_icon && (
<Avatar
src={op.user_icon}
size={24}
className={classNames(style.avatar, {
[style.defaultIcon]: op.user_icon === "defaultIcon",
})}
>
{op.user_icon === "defaultIcon" && op.label?.slice(0, 2)}
</Avatar>
)}
{optionLabel}
</Tooltip>
) : (
<>
{op.user_icon && (
<Avatar
src={op.user_icon}
size={24}
className={classNames(style.avatar, {
[style.defaultIcon]: op.user_icon === "defaultIcon",
})}
>
{op.user_icon === "defaultIcon" && op.label?.slice(0, 2)}
</Avatar>
)}
{optionLabel}
</>
)}
</Select.Option>
);
})}
</Select>
</Spin>
);
}