lodash#trim TypeScript Examples
The following examples show how to use
lodash#trim.
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: bot.ts From Adachi-BOT with MIT License | 6 votes |
private checkAtBOT( msg: sdk.GroupMessageEventData ): boolean {
const { number } = this.bot.config;
const atBOTReg: RegExp = new RegExp( `^ *\\[CQ:at,qq=${ number }.*]` );
const content: string = msg.raw_message;
if ( atBOTReg.test( content ) ) {
msg.raw_message = content
.replace( atBOTReg, "" )
.trim();
return true;
}
return false;
}
Example #2
Source File: index.ts From MyAPI with MIT License | 6 votes |
/**
* Trim the string props of an object
* @param object - An object with string props.
*/
export function trimStringProps<T> (object: T): T {
const newObject = JSON.parse(JSON.stringify(object)) as T
for (const key in object) {
if (object.hasOwnProperty(key)) {
const value = object[key]
newObject[key] = (isString(value) ? trim(value) : value ) as any
}
}
return newObject
}
Example #3
Source File: QuerySnippetNavigator.tsx From querybook with Apache License 2.0 | 6 votes |
@bind
@decorate(memoizeOne)
public getQuerySnippets(
querySnippetById: Record<number, IQuerySnippet>,
querySnippetIds: number[],
titleFilter: string
) {
const isEmptyFilter = trim(titleFilter).length === 0;
const titleFilterLower = titleFilter.toLowerCase();
return querySnippetIds
.map((id) => querySnippetById[id])
.filter(
(querySnippet) =>
isEmptyFilter ||
querySnippet.title.toLowerCase().includes(titleFilterLower)
);
}
Example #4
Source File: write-properties-file.ts From relate with GNU General Public License v3.0 | 6 votes |
export function writePropertiesFile(path: string, properties: PropertyEntries): Promise<void> {
const asText = join(
map(properties, ([key, val]) => {
const nowhitespace = trim(val);
return nowhitespace ? join([key, val], PROPERTIES_SEPARATOR) : key;
}),
NEW_LINE,
);
return writeFile(path, asText, 'utf8');
}
Example #5
Source File: read-properties-file.ts From relate with GNU General Public License v3.0 | 6 votes |
export async function readPropertiesFile(path: string): Promise<PropertyEntries> {
const conf = await readFile(path, 'utf8');
const lines = map(split(conf, NEW_LINE), trim);
return map(lines, (line): [string, string] => {
const [key, ...rest] = split(line, PROPERTIES_SEPARATOR);
return [key, join(rest, PROPERTIES_SEPARATOR)];
});
}
Example #6
Source File: save-field.tsx From admin with MIT License | 6 votes |
SaveFilterItem: React.FC<SaveFilterItemProps> = ({
saveFilter,
setName,
name,
}) => {
const onSave = () => {
const trimmedName = trim(name)
if (trimmedName !== "") {
saveFilter()
setName("")
}
}
return (
<div className="mt-2 flex w-full">
<InputField
className="pt-0 pb-1 max-w-[172px]"
placeholder="Name your filter..."
onChange={(e) => setName(e.target.value)}
value={name}
/>
<Button
className="border ml-2 border-grey-20"
variant="ghost"
size="small"
onClick={onSave}
>
Save
</Button>
</div>
)
}
Example #7
Source File: string.ts From dyngoose with ISC License | 6 votes |
toDynamo(value: Value): DynamoDB.AttributeValue {
if (typeof value !== 'string') {
throw new ValidationError(`Expected ${this.propertyName} to be a string, but was given a ${typeof value}`)
}
if (this.metadata?.trim === true) {
value = trim(value)
if (value === '') {
return {
NULL: true,
}
}
}
if (this.metadata?.uppercase === true) {
value = value.toUpperCase()
} else if (this.metadata?.lowercase === true) {
value = value.toLowerCase()
}
return {
S: value,
}
}
Example #8
Source File: text.ts From S2 with MIT License | 6 votes |
measureTextWidth = memoize(
(text: number | string = '', font: unknown): number => {
if (!font) {
return 0;
}
const { fontSize, fontFamily, fontWeight, fontStyle, fontVariant } =
font as CSSStyleDeclaration;
// copy G 里面的处理逻辑
ctx.font = [fontStyle, fontVariant, fontWeight, `${fontSize}px`, fontFamily]
.join(' ')
.trim();
return ctx.measureText(`${text}`).width;
},
(text: any, font) => [text, ...values(font)].join(''),
)
Example #9
Source File: reorder.ts From Adachi-BOT with MIT License | 6 votes |
export async function main(
{ sendMessage, messageData }: InputParameter
): Promise<void> {
const userID: number = messageData.user_id;
const list: number[] = messageData.raw_message
.split( " " )
.map( el => parseInt( trim( el ) ) );
const accounts: Private[] = privateClass.getUserPrivateList( userID );
if ( !checkList( list ) || accounts.length !== list.length ) {
await sendMessage( "序号排序列表格式不合法" );
return;
}
for ( let i = 0; i < list.length; i++ ) {
const pos: number = list[i];
accounts[pos - 1].updateID( i + 1 );
}
await sendMessage( "序号重排完成" );
}
Example #10
Source File: text.ts From S2 with MIT License | 5 votes |
isUpDataValue = (value: number | string): boolean => {
if (isNumber(value)) {
return value >= 0;
}
return !!value && !trim(value).startsWith('-');
}
Example #11
Source File: write-properties-file.test.ts From relate with GNU General Public License v3.0 | 5 votes |
describe('writePropertiesFile', () => {
test('Writes properties to file', async () => {
const plain: PropertyEntries = [
['bar.bam', 'baz'],
['bom.boz', 'true'],
];
const expected = trim(
replace(
`
bar.bam=baz
bom.boz=true
`,
WHITESPACE,
'',
),
);
const properties = await writePropertiesFile('plain', plain);
expect(properties).toEqual(expected);
});
test('Adds comments (without separator)', async () => {
const comments: PropertyEntries = [
['# hurr', ''],
['bar.bam', 'baz'],
['# durr', ''],
['bom.boz', 'true'],
];
const expected = trim(
replace(
`
# hurr
bar.bam=baz
# durr
bom.boz=true
`,
WHITESPACE,
'',
),
);
const properties = await writePropertiesFile('comments', comments);
expect(properties).toEqual(expected);
});
test('preserves whitespace', async () => {
const emptyKey: PropertyEntries = [
['bar.bam', 'baz'],
['', ''],
['bom', 'true'],
];
const expected = 'bar.bam=baz\n\nbom=true';
const properties = await writePropertiesFile('emptyKey', emptyKey);
expect(properties).toEqual(expected);
});
});
Example #12
Source File: str.monad.ts From relate with GNU General Public License v3.0 | 5 votes |
trim(): Str {
return Str.from(trim(`${this}`));
}
Example #13
Source File: bot.ts From Adachi-BOT with MIT License | 5 votes |
/* 正则检测处理消息 */
private async execute(
messageData: msg.Message,
sendMessage: msg.SendFunc,
cmdSet: BasicConfig[],
limits: string[],
unionRegExp: RegExp,
isPrivate: boolean
): Promise<void> {
const content: string = messageData.raw_message;
if ( this.bot.refresh.isRefreshing || !unionRegExp.test( content ) ) {
return;
}
if ( isPrivate && this.bot.config.addFriend && messageData.sub_type !== "friend" ) {
await this.bot.client.sendPrivateMsg( messageData.user_id, "请先添加 BOT 为好友再尝试发送指令" );
return;
}
const usable: BasicConfig[] = cmdSet.filter( el => !limits.includes( el.cmdKey ) );
for ( let cmd of usable ) {
const res: MatchResult = cmd.match( content );
if ( res.type === "unmatch" ) {
continue;
}
if ( res.type === "order" ) {
const text: string = cmd.ignoreCase
? content.toLowerCase() : content;
messageData.raw_message = trim(
msg.removeStringPrefix( text, res.header.toLowerCase() )
.replace( / +/g, " " )
);
}
cmd.run( {
sendMessage, ...this.bot,
messageData, matchResult: res
} );
/* 数据统计与收集 */
const userID: number = messageData.user_id;
const groupID: number = msg.isGroupMessage( messageData ) ? messageData.group_id : -1;
await this.bot.redis.addSetMember( `adachi.user-used-groups-${ userID }`, groupID );
await this.bot.redis.incHash( "adachi.hour-stat", userID.toString(), 1 );
await this.bot.redis.incHash( "adachi.command-stat", cmd.cmdKey, 1 );
return;
}
}
Example #14
Source File: VariableInput.tsx From grafana-chinese with Apache License 2.0 | 5 votes |
private shouldUpdateValue(value: string) {
return trim(value ?? '').length > 0 || trim(this.props.value ?? '').length > 0;
}
Example #15
Source File: generate.spec.ts From prisma-nestjs-graphql with MIT License | 5 votes |
describe('emit single and decorators', () => {
before(async () => {
({ project, sourceFiles } = await testGenerate({
schema: `
model User {
id Int @id
/// @Validator.MinLength(3)
name String
/// @PropertyType({ name: 'G.Email', from: 'graphql-type-email', input: true })
email String?
}
`,
options: [
`emitSingle = true`,
`outputFilePattern = "{name}.{type}.ts"`,
`fields_Validator_from = "class-validator"`,
`fields_Validator_input = true`,
],
}));
setSourceFile('index.ts');
});
it('should contain custom decorator import', () => {
const importDeclaration = importDeclarations.find(
x => x.moduleSpecifier === 'graphql-type-email',
);
expect(importDeclaration).toEqual(
expect.objectContaining({
namespaceImport: 'G',
}),
);
});
it('validator namespace for name should be imported', () => {
expect(importDeclarations).toContainEqual(
expect.objectContaining({
namespaceImport: 'Validator',
}),
);
});
describe('user create input name', () => {
let property: PropertyDeclaration;
before(() => {
property = sourceFile.getClass('UserCreateInput')?.getProperty('name')!;
});
it('decorator validator', () => {
const d = property.getDecorator(d => d.getFullText().includes('MinLength'));
expect(trim(d?.getFullText())).toEqual('@Validator.MinLength(3)');
});
});
});
Example #16
Source File: compoundJSONSchemaYAML.ts From hub with Apache License 2.0 | 4 votes |
compoundJSONSchemaYAML = (schema: JSONSchema, savedOpts: { [key: string]: number }): FormattedValuesSchema => {
const title = schema.title ? `# ${schema.title}` : '';
let paths: string[] = [];
const getValue = (value: JSONSchema, level: number): string | undefined => {
if (isUndefined(value.default)) {
return undefined;
}
if (isNull(value.default)) {
return 'null';
}
switch (isArray(value.type) ? value.type[0] : value.type) {
case 'object':
return isEmpty(value.default) ? '{}' : JSON.stringify(value.default);
case 'array':
return isArray(value.default)
? value.default.length === 0
? `[]`
: `${(value.default as string[]).map((val: string) => `\n${repeat(' ', (level + 1) * 2)}- ${val}`)}`
: '';
case 'boolean':
case 'integer':
return value.default!.toString();
case 'string':
const isLongText = (value.default as string).length > 40;
if (isLongText) {
return `|-\n\n${repeat(' ', (level + 1) * 2)}${value.default}`;
} else {
return formatStringForYAML(value.default as string) || `""`;
}
default:
return value.default ? value.default.toString() : undefined;
}
};
const items = {};
function checkProperties(props: any, level: number, isArrayParent: boolean, pathSteps: string[] = [], path?: string) {
Object.keys(props).forEach((propName: string, index: number) => {
let value: JSONSchema | undefined = props[propName] as JSONSchema;
let isCurrentArrayParent = false;
if (
value &&
!isNull(value.type) &&
value.type === 'array' &&
value.items &&
(value.items as JSONSchema).hasOwnProperty('properties')
) {
isCurrentArrayParent = true;
}
const currentSteps: string[] = [...pathSteps, propName];
const currentPath = getJMESPathForValuesSchema(isCurrentArrayParent ? `${propName}[0]` : propName, path);
paths.push(currentPath);
const checkCombinations = (valueToCheck: JSONSchema) => {
if (valueToCheck.oneOf) {
value = valueToCheck.oneOf[savedOpts[currentPath] || 0] as JSONSchema;
} else if (valueToCheck.anyOf) {
value = valueToCheck.anyOf[savedOpts[currentPath] || 0] as JSONSchema;
}
};
if (value && isUndefined(value.$ref)) {
checkCombinations(value);
} else {
value = undefined;
}
if (isUndefined(value) || isNull(value)) return;
const defaultValue = getValue(value, level);
if (isCurrentArrayParent) {
set(items, currentSteps, {
level: level,
title: value.title,
properties: {},
});
checkProperties(
(value.items as JSONSchema).properties!,
level + 1,
isCurrentArrayParent,
[...currentSteps, 'properties'],
currentPath
);
} else {
if (value.properties) {
set(items, currentSteps, {
level: level,
title: value.title,
properties: {},
hasDecorator: isArrayParent && index === 0,
isArrayParent: isArrayParent,
});
checkProperties(
value.properties,
isArrayParent ? level + 2 : level + 1,
isCurrentArrayParent,
[...currentSteps, 'properties'],
currentPath
);
} else if (!isUndefined(defaultValue)) {
set(items, currentSteps, {
level: level,
value: defaultValue,
title: value.title,
hasDecorator: isArrayParent && index === 0,
isArrayParent: isArrayParent,
});
}
}
});
}
if (schema.properties) {
checkProperties(schema.properties, 0, false);
}
const yamlContent = prepareContent(items);
return {
yamlContent: trim(yamlContent) !== '' ? `${title}${yamlContent}` : undefined,
paths: paths,
};
}
Example #17
Source File: index.tsx From hub with Apache License 2.0 | 4 votes |
AuthorizationSection = (props: Props) => {
const { ctx, dispatch } = useContext(AppCtx);
const siteName = getMetaTag('siteName');
const updateActionBtn = useRef<RefActionBtn>(null);
const [apiError, setApiError] = useState<string | JSX.Element | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [isSaving, setIsSaving] = useState<boolean>(false);
const [isTesting, setIsTesting] = useState<boolean>(false);
const [savedOrgPolicy, setSavedOrgPolicy] = useState<OrganizationPolicy | undefined>(undefined);
const [orgPolicy, setOrgPolicy] = useState<OrganizationPolicy | undefined | null>(undefined);
const [invalidPolicy, setInvalidPolicy] = useState<boolean>(false);
const [invalidPolicyDataJSON, setInvalidPolicyDataJSON] = useState<boolean>(false);
const [selectedOrg, setSelectedOrg] = useState<string | undefined>(undefined);
const [members, setMembers] = useState<string[] | undefined>(undefined);
const [notGetPolicyAllowed, setNotGetPolicyAllowed] = useState<boolean>(false);
const [updatePolicyAllowed, setUpdatePolicyAllowed] = useState<boolean>(false);
const [confirmationModal, setConfirmationModal] = useState<ConfirmationModal>({ open: false });
const getPredefinedPolicy = (name?: string): AuthorizationPolicy | undefined => {
let policy = PREDEFINED_POLICIES.find((item: AuthorizationPolicy) => item.name === name);
if (!isUndefined(policy) && !isUndefined(members)) {
policy = {
...policy,
data: {
roles: {
...policy.data.roles,
owner: {
users: members,
},
},
},
};
}
return policy;
};
const onPayloadChange = (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
let updatedOrgPolicy: OrganizationPolicy | undefined = undefined;
if (value === 'predefined') {
if (savedOrgPolicy && savedOrgPolicy.predefinedPolicy) {
updatedOrgPolicy = {
...savedOrgPolicy,
authorizationEnabled: true,
};
} else {
const defaultPolicy = getPredefinedPolicy(DEFAULT_POLICY_NAME);
if (defaultPolicy) {
updatedOrgPolicy = {
...orgPolicy!,
customPolicy: null,
predefinedPolicy: defaultPolicy.name,
policyData: stringifyPolicyData(defaultPolicy.data),
};
}
}
checkPolicyChanges(
() => setOrgPolicy(updatedOrgPolicy!),
PolicyChangeAction.OnSwitchFromCustomToPredefinedPolicy
);
} else {
let updatedOrgPolicy: OrganizationPolicy | undefined = undefined;
if (savedOrgPolicy && savedOrgPolicy.customPolicy) {
updatedOrgPolicy = {
...savedOrgPolicy,
authorizationEnabled: true,
};
} else {
updatedOrgPolicy = {
...orgPolicy!,
customPolicy: null,
predefinedPolicy: null,
policyData: null,
};
}
checkPolicyChanges(
() => setOrgPolicy(updatedOrgPolicy!),
PolicyChangeAction.OnSwitchFromPredefinedToCustomPolicy
);
}
};
const checkIfUnsavedChanges = (): boolean => {
const lostData = checkUnsavedPolicyChanges(savedOrgPolicy!, orgPolicy!);
return lostData.lostData;
};
async function triggerTestInRegoPlayground() {
try {
setIsTesting(true);
let policy: string = '';
if (orgPolicy!.predefinedPolicy) {
const predefined = getPredefinedPolicy(orgPolicy!.predefinedPolicy);
if (predefined) {
policy = predefined.policy;
}
} else {
policy = orgPolicy!.customPolicy || '';
}
const data = prepareRegoPolicyForPlayground(policy, JSON.parse(orgPolicy!.policyData!), ctx.user!.alias);
const share: RegoPlaygroundResult = await API.triggerTestInRegoPlayground(data);
const popup = window.open(share.result, '_blank');
if (isNull(popup)) {
alertDispatcher.postAlert({
type: 'warning',
message:
'You have Pop-up windows blocked for this site. Please allow them so that we can open the OPA Playground for you.',
});
}
setIsTesting(false);
} catch (err: any) {
setIsTesting(false);
alertDispatcher.postAlert({
type: 'danger',
message: 'An error occurred opening the Playground, please try again later.',
});
}
}
async function getAuthorizationPolicy() {
try {
setIsLoading(true);
const policy = await API.getAuthorizationPolicy(selectedOrg!);
const formattedPolicy = {
authorizationEnabled: policy.authorizationEnabled,
predefinedPolicy: policy.predefinedPolicy || null,
customPolicy: policy.customPolicy || null,
policyData: policy.policyData ? stringifyPolicyData(policy.policyData) : null,
};
setSavedOrgPolicy(formattedPolicy);
setOrgPolicy(formattedPolicy);
setNotGetPolicyAllowed(false);
setUpdatePolicyAllowed(
authorizer.check({
organizationName: selectedOrg!,
action: AuthorizerAction.UpdateAuthorizationPolicy,
user: ctx.user!.alias,
})
);
setIsLoading(false);
} catch (err: any) {
setIsLoading(false);
if (err.kind === ErrorKind.Unauthorized) {
props.onAuthError();
} else if (err.kind === ErrorKind.Forbidden) {
setNotGetPolicyAllowed(true);
setOrgPolicy(null);
} else {
setNotGetPolicyAllowed(false);
setOrgPolicy(null);
alertDispatcher.postAlert({
type: 'danger',
message: 'An error occurred getting the policy from the organization, please try again later.',
});
}
}
}
async function updateAuthorizationPolicy() {
try {
setIsSaving(true);
await API.updateAuthorizationPolicy(selectedOrg!, orgPolicy!);
getAuthorizationPolicy();
// Update allowed actions and re-render button
authorizer.getAllowedActionsList(() => updateActionBtn.current!.reRender());
setIsSaving(false);
} catch (err: any) {
setIsSaving(false);
if (err.kind !== ErrorKind.Unauthorized) {
let error: string | JSX.Element = compoundErrorMessage(err, 'An error occurred updating the policy');
error = (
<>
{error}. For more information please see the{' '}
<ExternalLink
href="https://github.com/artifacthub/hub/blob/master/docs/authorization.md"
className="text-primary fw-bold"
label="Open documentation"
>
documentation
</ExternalLink>
.
</>
);
if (err.kind === ErrorKind.Forbidden) {
error = 'You do not have permissions to update the policy from the organization.';
setUpdatePolicyAllowed(false);
}
setApiError(error);
} else {
props.onAuthError();
}
}
}
async function fetchMembers() {
try {
const membersList: Member[] = await API.getAllOrganizationMembers(ctx.prefs.controlPanel.selectedOrg!);
setMembers(membersList.map((member: Member) => member.alias));
} catch (err: any) {
setMembers(undefined);
}
}
const onSaveAuthorizationPolicy = () => {
const policy = orgPolicy!.customPolicy || orgPolicy!.predefinedPolicy;
if (isNull(policy) || isUndefined(policy) || trim(policy) === '') {
setInvalidPolicy(true);
} else if (!isValidJSON(orgPolicy!.policyData || '')) {
setInvalidPolicyDataJSON(true);
} else {
checkPolicyChanges(updateAuthorizationPolicy, PolicyChangeAction.OnSavePolicy);
}
};
const onAuthorizationEnabledChange = () => {
let extraData = {};
const authorized = !orgPolicy!.authorizationEnabled;
const defaultPolicy = getPredefinedPolicy(DEFAULT_POLICY_NAME);
if (
authorized &&
(isNull(savedOrgPolicy!.customPolicy) || isUndefined(savedOrgPolicy!.customPolicy)) &&
(isNull(savedOrgPolicy!.predefinedPolicy) || isUndefined(savedOrgPolicy!.predefinedPolicy)) &&
!isUndefined(defaultPolicy)
) {
extraData = {
predefinedPolicy: defaultPolicy.name,
policyData: stringifyPolicyData(defaultPolicy.data),
};
}
const updatedOrgPolicy = {
...savedOrgPolicy!,
...extraData,
authorizationEnabled: authorized,
};
if (!authorized) {
checkPolicyChanges(() => setOrgPolicy(updatedOrgPolicy), PolicyChangeAction.OnDisableAuthorization);
} else {
setOrgPolicy(updatedOrgPolicy);
}
};
const onPredefinedPolicyChange = (e: ChangeEvent<HTMLSelectElement>) => {
e.preventDefault();
const activePredefinedPolicy = getPredefinedPolicy(e.target.value);
const updatedOrgPolicy = {
...orgPolicy!,
predefinedPolicy: e.target.value,
policyData: !isUndefined(activePredefinedPolicy) ? stringifyPolicyData(activePredefinedPolicy.data) : '',
};
checkPolicyChanges(() => setOrgPolicy(updatedOrgPolicy!), PolicyChangeAction.OnChangePredefinedPolicy);
};
const checkPolicyChanges = (onConfirmAction: () => void, action?: PolicyChangeAction) => {
const currentPredefinedPolicy =
orgPolicy && orgPolicy.predefinedPolicy ? getPredefinedPolicy(orgPolicy.predefinedPolicy) : undefined;
const lostData = checkUnsavedPolicyChanges(
savedOrgPolicy!,
orgPolicy!,
action,
currentPredefinedPolicy ? currentPredefinedPolicy.data : undefined
);
if (lostData.lostData) {
setConfirmationModal({
open: true,
message: lostData.message,
onConfirm: onConfirmAction,
});
} else {
onConfirmAction();
}
};
useEffect(() => {
if (selectedOrg) {
getAuthorizationPolicy();
fetchMembers();
}
}, [selectedOrg]); /* eslint-disable-line react-hooks/exhaustive-deps */
useEffect(() => {
if (ctx.prefs.controlPanel.selectedOrg) {
if (selectedOrg !== ctx.prefs.controlPanel.selectedOrg) {
if (!checkIfUnsavedChanges()) {
setSelectedOrg(ctx.prefs.controlPanel.selectedOrg);
} else {
const warningPrompt = window.confirm(
'You have some unsaved changes in your policy data. If you continue without saving, those changes will be lost.'
);
if (!warningPrompt) {
dispatch(updateOrg(selectedOrg!));
} else {
setSelectedOrg(ctx.prefs.controlPanel.selectedOrg);
}
}
}
}
}, [ctx.prefs.controlPanel.selectedOrg]); /* eslint-disable-line react-hooks/exhaustive-deps */
const onBeforeUnload = (e: BeforeUnloadEvent) => {
e.preventDefault();
e.returnValue =
'You have some unsaved changes in your policy data. If you continue without saving, those changes will be lost.';
};
useEffect(() => {
if (checkIfUnsavedChanges()) {
window.addEventListener('beforeunload', onBeforeUnload);
} else {
window.removeEventListener('beforeunload', onBeforeUnload);
}
return () => {
window.removeEventListener('beforeunload', onBeforeUnload);
};
}, [orgPolicy]); /* eslint-disable-line react-hooks/exhaustive-deps */
return (
<main role="main" className="p-0">
{(isUndefined(orgPolicy) || isLoading) && <Loading />}
<Prompt
when={!isNull(orgPolicy) && !isUndefined(orgPolicy) && !notGetPolicyAllowed && checkIfUnsavedChanges()}
message="You have some unsaved changes in your policy data. If you continue without saving, those changes will be lost."
/>
<div className={`h3 pb-2 border-bottom ${styles.title}`}>Authorization</div>
<div className="mt-4 mt-md-5" onClick={() => setApiError(null)}>
<p>
{siteName} allows you to setup fine-grained access control based on authorization policies. Authorization
polices are written in{' '}
<ExternalLink
href="https://www.openpolicyagent.org/docs/latest/#rego"
className="text-primary fw-bold"
label="Open rego documentation"
>
rego
</ExternalLink>{' '}
and they are evaluated using the{' '}
<ExternalLink
href="https://www.openpolicyagent.org"
className="text-primary fw-bold"
label="Open Open Policy Agent documentation"
>
Open Policy Agent
</ExternalLink>
. Depending on your requirements, you can use a predefined policy and only supply a data file, or you can
provide your custom policy for maximum flexibility. For more information please see the{' '}
<ExternalLink href="/docs/authorization" className="text-primary fw-bold" label="Open documentation">
documentation
</ExternalLink>
.
</p>
{(isNull(orgPolicy) || isUndefined(orgPolicy)) && notGetPolicyAllowed && (
<NoData>You are not allowed to manage this organization's authorization policy</NoData>
)}
{orgPolicy && (
<>
<div className="form-check form-switch mb-4">
<input
id="activeAuthorization"
type="checkbox"
className="form-check-input"
value="true"
role="switch"
onChange={onAuthorizationEnabledChange}
checked={orgPolicy.authorizationEnabled}
disabled={!updatePolicyAllowed}
/>
<label className="form-check-label" htmlFor="activeAuthorization">
Fine-grained access control
</label>
</div>
{orgPolicy.authorizationEnabled && (
<>
<label className={`form-label ${styles.label}`} htmlFor="payload">
<span className="fw-bold">Select authorization policy:</span>
</label>
<div className="d-flex flex-row mb-2">
{PAYLOAD_OPTION.map((item: Option) => {
const activeOption = !isNull(orgPolicy.predefinedPolicy) ? 'predefined' : 'custom';
return (
<div className="form-check me-4 mb-2" key={`payload_${item.name}`}>
<input
className="form-check-input"
type="radio"
id={item.name}
name="payload"
value={item.name}
checked={activeOption === item.name}
onChange={onPayloadChange}
disabled={!updatePolicyAllowed}
/>
<label className="form-check-label" htmlFor={item.name}>
{item.label}
</label>
</div>
);
})}
</div>
{orgPolicy.predefinedPolicy && (
<div className=" w-75 mb-4">
<select
className="form-select"
aria-label="org-select"
value={orgPolicy.predefinedPolicy || ''}
onChange={onPredefinedPolicyChange}
required={!isNull(orgPolicy.predefinedPolicy)}
disabled={!updatePolicyAllowed}
>
<option value="" disabled>
Select policy
</option>
{PREDEFINED_POLICIES.map((item: Option) => (
<option key={`policy_${item.name}`} value={item.name}>
{item.label}
</option>
))}
</select>
<div className={`invalid-feedback ${styles.fieldFeedback}`}>This field is required</div>
</div>
)}
<div className="d-flex flex-row align-self-stretch">
<div className="d-flex flex-column w-50 pe-2">
<div className="text-uppercase text-muted mb-2">Policy</div>
<div className="flex-grow-1">
<CodeEditor
mode="rego"
value={
orgPolicy.predefinedPolicy
? getPredefinedPolicy(orgPolicy.predefinedPolicy)!.policy
: orgPolicy.customPolicy
}
onChange={(value: string) => {
if (invalidPolicy) {
setInvalidPolicy(false);
}
setOrgPolicy({
...orgPolicy!,
customPolicy: value || null,
});
}}
disabled={orgPolicy.predefinedPolicy || !updatePolicyAllowed}
/>
{invalidPolicy && (
<small className="text-danger">
<span className="fw-bold">Error: </span> This field is required
</small>
)}
</div>
</div>
<div className="d-flex flex-column w-50 ps-2">
<div className="text-uppercase text-muted mb-2">Data</div>
<div className="flex-grow-1">
<CodeEditor
value={orgPolicy.policyData}
mode="javascript"
onChange={(value: string) => {
if (invalidPolicyDataJSON) {
setInvalidPolicyDataJSON(false);
}
setOrgPolicy({
...orgPolicy!,
policyData: value || null,
});
}}
disabled={!updatePolicyAllowed}
/>
{invalidPolicyDataJSON && (
<small className="text-danger">
<span className="fw-bold">Error: </span> Invalid JSON format
</small>
)}
</div>
</div>
</div>
</>
)}
<div className="d-flex flex-row mt-4">
{orgPolicy.authorizationEnabled && (
<button
type="button"
className="btn btn-sm btn-success"
onClick={triggerTestInRegoPlayground}
aria-label="Test in playground"
>
{isTesting ? (
<>
<span className="spinner-grow spinner-grow-sm" role="status" aria-hidden="true" />
<span className="ms-2">Preparing Playground...</span>
</>
) : (
<div className="d-flex flex-row align-items-center text-uppercase">
<RiTestTubeFill className="me-2" /> <div>Test in Playground</div>
</div>
)}
</button>
)}
<div className="ms-auto">
<ActionBtn
ref={updateActionBtn}
className="btn btn-sm btn-outline-secondary"
onClick={(e: ReactMouseEvent<HTMLButtonElement>) => {
e.preventDefault();
onSaveAuthorizationPolicy();
}}
action={AuthorizerAction.UpdateAuthorizationPolicy}
disabled={isSaving}
label="Update authorization policy"
>
<>
{isSaving ? (
<>
<span className="spinner-grow spinner-grow-sm" role="status" aria-hidden="true" />
<span className="ms-2">Saving</span>
</>
) : (
<div className="d-flex flex-row align-items-center text-uppercase">
<FaPencilAlt className="me-2" />
<div>Save</div>
</div>
)}
</>
</ActionBtn>
</div>
</div>
</>
)}
<Alert message={apiError} type="danger" onClose={() => setApiError(null)} />
</div>
{confirmationModal.open && (
<Modal
className={`d-inline-block ${styles.modal}`}
closeButton={
<>
<button
className="btn btn-sm btn-outline-secondary text-uppercase"
onClick={() => setConfirmationModal({ open: false })}
aria-label="Cancel"
>
Cancel
</button>
<button
className="btn btn-sm btn-outline-secondary text-uppercase ms-3"
onClick={(e) => {
e.preventDefault();
confirmationModal.onConfirm!();
setConfirmationModal({ open: false });
}}
aria-label="Confirm"
>
Ok
</button>
</>
}
header={<div className={`h3 m-2 flex-grow-1 ${styles.title}`}>Confirm action</div>}
onClose={() => setConfirmationModal({ open: false })}
open
>
<div className="mt-3 mw-100 text-center">
<p>{confirmationModal.message!}</p>
</div>
</Modal>
)}
</main>
);
}
Example #18
Source File: FlowsFilterInput.tsx From hubble-ui with Apache License 2.0 | 4 votes |
FlowsFilterInput = (props: Props) => {
const [userInput, setUserInput] = useState<string>('');
const onClear = useCallback(() => {
props.onChange?.([]);
}, [props.onChange]);
const createNewItemRenderer = useCallback(
(
query: string,
active: boolean,
handleClick: React.MouseEventHandler<HTMLElement>,
) => {
if (props.filters.some(({ query: text }) => text === query)) {
return undefined;
}
return (
<MenuItem
onClick={handleClick}
active={active}
text={`Search "${query}"`}
icon="search"
/>
);
},
[props.filters],
);
const createNewItemFromQuery = (userInput: string) => {
const filter = FilterEntry.parse(userInput);
if (filter?.isLabel) {
filter.prepareLabel();
}
return filter;
};
const onQueryChange = useCallback((query: string) => {
setUserInput(query.replace(/\s/, ''));
}, []);
// prettier-ignore
const onItemSelect = useCallback((item: FilterEntry | null) => {
if (!item || trim(item.query).length === 0) return;
props.onChange?.([...props.filters, item]);
setUserInput('');
}, [props.filters, props.onChange, userInput]);
// prettier-ignore
const handleTagDelete = useCallback((val: string, idx: number) => {
props.onChange?.(
props.filters.filter((_: FilterEntry, i: number) => i !== idx),
);
}, [props.filters, props.onChange]);
const rightElement = props.filters.length ? (
<Button minimal icon="cross" onClick={onClear} />
) : undefined;
return (
<FilterMultiSelect
initialContent={null}
className={css.container}
query={userInput}
selectedItems={props.filters}
onQueryChange={onQueryChange}
onItemSelect={onItemSelect}
createNewItemFromQuery={createNewItemFromQuery}
createNewItemRenderer={createNewItemRenderer}
itemRenderer={itemRenderer}
tagRenderer={tagRenderer}
itemPredicate={useCallback(() => false, [])}
items={[]}
popoverProps={{
minimal: true,
usePortal: true,
openOnTargetFocus: false,
}}
resetOnSelect={true}
noResults={<MenuItem disabled={true} text="No results." />}
tagInputProps={{
onRemove: handleTagDelete,
tagProps: { minimal: true },
rightElement: rightElement,
className: Classes.INPUT,
placeholder:
'Filter by: label key=val, ip=1.1.1.1, dns=google.com, identity=42, pod=frontend',
}}
/>
);
}
Example #19
Source File: index.ts From S2 with MIT License | 4 votes |
copyData = (
sheetInstance: SpreadSheet,
split: string,
formatOptions?: FormatOptions,
): string => {
const { isFormatHeader, isFormatData } = getFormatOptions(formatOptions);
const { rowsHierarchy, rowLeafNodes, colLeafNodes, getCellMeta } =
sheetInstance?.facet?.layoutResult;
const { maxLevel } = rowsHierarchy;
const { valueInCols } = sheetInstance.dataCfg.fields;
// Generate the table header.
const rowsHeader = rowsHierarchy.sampleNodesForAllLevels.map((item) =>
sheetInstance.dataSet.getFieldName(item.key),
);
// get max query property length
const rowLength = rowLeafNodes.reduce((pre, cur) => {
const length = cur.query ? Object.keys(cur.query).length : 0;
return length > pre ? length : pre;
}, 0);
// Generate the table body.
let detailRows = [];
let maxRowLength = 0;
if (!sheetInstance.isPivotMode()) {
detailRows = processValueInDetail(sheetInstance, split, isFormatData);
} else {
// Filter out the related row head leaf nodes.
const caredRowLeafNodes = rowLeafNodes.filter((row) => row.height !== 0);
for (const rowNode of caredRowLeafNodes) {
let tempLine = [];
if (isFormatHeader) {
tempLine = getRowNodeFormatData(rowNode);
} else {
// Removing the space at the beginning of the line of the label.
rowNode.label = trim(rowNode?.label);
const id = rowNode.id.replace(ROOT_BEGINNING_REGEX, '');
tempLine = id.split(ID_SEPARATOR);
}
// TODO 兼容下钻,需要获取下钻最大层级
const totalLevel = maxLevel + 1;
const emptyLength = totalLevel - tempLine.length;
if (emptyLength > 0) {
tempLine.push(...new Array(emptyLength));
}
// 指标挂行头且为平铺模式下,获取指标名称
const lastLabel = sheetInstance.dataSet.getFieldName(last(tempLine));
tempLine[tempLine.length - 1] = lastLabel;
for (const colNode of colLeafNodes) {
if (valueInCols) {
const viewMeta = getCellMeta(rowNode.rowIndex, colNode.colIndex);
tempLine.push(
processValueInCol(viewMeta, sheetInstance, isFormatData),
);
} else {
const viewMeta = getCellMeta(rowNode.rowIndex, colNode.colIndex);
const lintItem = processValueInRow(
viewMeta,
sheetInstance,
isFormatData,
);
if (isArray(lintItem)) {
tempLine = tempLine.concat(...lintItem);
} else {
tempLine.push(lintItem);
}
}
}
maxRowLength = max([tempLine.length, maxRowLength]);
const lineString = tempLine
.map((value) => getCsvString(value))
.join(split);
detailRows.push(lineString);
}
}
// Generate the table header.
let headers: string[][] = [];
if (isEmpty(colLeafNodes) && !sheetInstance.isPivotMode()) {
// when there is no column in detail mode
headers = [rowsHeader];
} else {
// 当列头label为array时用于补全其他层级的label
let arrayLength = 0;
// Get the table header of Columns.
let tempColHeader = clone(colLeafNodes).map((colItem) => {
let curColItem = colItem;
const tempCol = [];
// Generate the column dimensions.
while (curColItem.level !== undefined) {
let label = getHeaderLabel(curColItem.label);
if (isArray(label)) {
arrayLength = max([arrayLength, size(label)]);
} else {
// label 为数组时不进行格式化
label = isFormatHeader ? getNodeFormatLabel(curColItem) : label;
}
tempCol.push(label);
curColItem = curColItem.parent;
}
return tempCol;
});
if (arrayLength > 1) {
tempColHeader = processColHeaders(tempColHeader, arrayLength);
}
const colLevels = tempColHeader.map((colHeader) => colHeader.length);
const colLevel = max(colLevels);
const colHeader: string[][] = [];
// Convert the number of column dimension levels to the corresponding array.
for (let i = colLevel - 1; i >= 0; i -= 1) {
// The map of data set: key-name
const colHeaderItem = tempColHeader
// total col completion
.map((item) =>
item.length < colLevel
? [...new Array(colLevel - item.length), ...item]
: item,
)
.map((item) => item[i])
.map((colItem) => sheetInstance.dataSet.getFieldName(colItem));
colHeader.push(flatten(colHeaderItem));
}
// Generate the table header.
headers = colHeader.map((item, index) => {
if (sheetInstance.isPivotMode()) {
const { columns, rows, data } = sheetInstance.facet.cornerHeader.cfg;
const colNodes = data.filter(
({ cornerType }) => cornerType === CornerNodeType.Col,
);
const rowNodes = data.filter(
({ cornerType }) => cornerType === CornerNodeType.Row,
);
if (index < colHeader.length - 1) {
return [
...Array(rowLength - 1).fill(''),
colNodes.find(({ field }) => field === columns[index])?.label || '',
...item,
];
}
if (index < colHeader.length) {
return [
...rows.map(
(row) => rowNodes.find(({ field }) => field === row)?.label || '',
),
...item,
];
}
return rowsHeader.concat(...item);
}
return index < colHeader.length
? Array(rowLength)
.fill('')
.concat(...item)
: rowsHeader.concat(...item);
});
}
const headerRow = headers
.map((header) => {
const emptyLength = maxRowLength - header.length;
if (emptyLength > 0) {
header.unshift(...new Array(emptyLength));
}
return header.map((h) => getCsvString(h)).join(split);
})
.join('\r\n');
const data = [headerRow].concat(detailRows);
const result = data.join('\r\n');
return result;
}
Example #20
Source File: SearchGithubRepo.tsx From TidGi-Desktop with Mozilla Public License 2.0 | 4 votes |
function SearchGithubRepoResultList({
githubWikiUrl,
githubWikiUrlSetter,
wikiFolderNameSetter,
isCreateMainWorkspace,
githubUsername,
accessToken,
}: Props & ITokens): JSX.Element {
const { t } = useTranslation();
const onSelectRepo = useCallback(
(url: string, name: string) => {
githubWikiUrlSetter(url);
typeof wikiFolderNameSetter === 'function' && wikiFolderNameSetter(name);
},
[githubWikiUrlSetter, wikiFolderNameSetter],
);
const [githubRepoSearchString, githubRepoSearchStringSetter] = useState('wiki');
const loadCount = 10;
// eslint-disable-next-line @typescript-eslint/unbound-method
const { loading, error, data, refetch } = useQuery<IGithubSearchRepoQuery>(SEARCH_REPO_QUERY, {
variables: {
first: loadCount,
queryString: `user:${githubUsername} ${githubRepoSearchString}`,
login: githubUsername,
},
skipCache: true,
});
const refetchDebounced = useDebouncedCallback(refetch, [], 300);
// clear list on logout, which will cause accessToken change
useEffect(() => {
const timeoutHandle = setTimeout(async () => {
await refetchDebounced();
}, 100);
return () => clearTimeout(timeoutHandle);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [githubUsername, accessToken]);
// try refetch on error
const [retryInterval, retryIntervalSetter] = useState(100);
useEffect(() => {
if (error !== undefined && githubUsername.length > 0 && accessToken.length > 0) {
const timeoutHandle = setTimeout(async () => {
await refetchDebounced();
retryIntervalSetter(retryInterval * 10);
}, retryInterval);
return () => clearTimeout(timeoutHandle);
}
return () => {};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [error, githubUsername, accessToken, retryInterval]);
const [createRepository] = useMutation(CREATE_REPO_MUTATION);
const repositoryCount = data?.search?.repositoryCount;
const repoList: IGithubSearchNode[] = useMemo(
() => (data !== undefined && (repositoryCount ?? 0) > 0 ? data.search.edges.map(({ node }) => node) : []),
[data, repositoryCount],
);
// auto select first one after first search
useEffect(() => {
if (githubWikiUrl?.length === 0 && repoList.length > 0) {
onSelectRepo(repoList[0].url, repoList[0].name);
}
}, [repoList, githubWikiUrl, onSelectRepo]);
const [isCreatingRepo, isCreatingRepoSetter] = useState(false);
const githubUserID = data?.repositoryOwner?.id;
const wikiUrlToCreate = `https://github.com/${githubUsername ?? '???'}/${githubRepoSearchString}`;
const isCreateNewRepo = trim(githubWikiUrl) === wikiUrlToCreate;
const githubPagesUrl = `https://${githubUsername ?? '???'}.github.io/${githubRepoSearchString}`;
let helperText = '';
if (error !== undefined) {
helperText = t('AddWorkspace.CanNotLoadList');
}
if (repositoryCount !== undefined && repositoryCount > loadCount) {
helperText = t('AddWorkspace.OmitMoreResult', { loadCount });
}
return (
<RepoSearchContainer>
<RepoSearchInput
fullWidth
onChange={(event) => {
githubRepoSearchStringSetter(event.target.value);
}}
label={t('AddWorkspace.SearchGithubRepoName')}
value={githubRepoSearchString}
helperText={helperText}
/>
{(loading || isCreatingRepo) && <LinearProgress variant="query" />}
<List component="nav" aria-label="main mailbox folders">
{repoList.map(({ name, url }) => (
<ListItem button key={url} onClick={() => onSelectRepo(url, name)} selected={trim(githubWikiUrl) === trim(url)}>
<ListItemIcon>
<FolderIcon />
</ListItemIcon>
<ListItemText primary={name} />
</ListItem>
))}
{error === undefined && !loading && !isCreatingRepo && !repoList.some(({ url }) => trim(url) === wikiUrlToCreate) && githubRepoSearchString && (
<ListItem
button
key={wikiUrlToCreate}
onClick={async () => {
isCreatingRepoSetter(true);
await createRepository({
variables: {
repoName: githubRepoSearchString,
homePageUrl: isCreateMainWorkspace ? githubPagesUrl : undefined,
ownerId: githubUserID,
visibility: isCreateMainWorkspace ? 'PUBLIC' : 'PRIVATE',
},
});
// wait for Github update their db
await Promise.delay(1000);
await refetchDebounced();
isCreatingRepoSetter(false);
githubWikiUrlSetter(wikiUrlToCreate);
}}
selected={isCreateNewRepo}>
<ListItemIcon>
<CreateNewFolderIcon />
</ListItemIcon>
<ListItemText
primary={`${
isCreateMainWorkspace ? t('AddWorkspace.CreatePublicRepository') : t('AddWorkspace.CreatePrivateRepository')
} ${githubRepoSearchString}`}
/>
</ListItem>
)}
</List>
{repoList.length === 0 && (
<ReloadButton color="secondary" endIcon={<CachedIcon />} onClick={async () => await refetchDebounced()}>
{t('AddWorkspace.Reload')}
</ReloadButton>
)}
</RepoSearchContainer>
);
}
Example #21
Source File: create-config.ts From prisma-nestjs-graphql with MIT License | 4 votes |
export function createConfig(data: Record<string, unknown>) {
const config = merge({}, unflatten(data, { delimiter: '_' })) as Record<
string,
unknown
>;
const $warnings: string[] = [];
const configOutputFilePattern = String(
config.outputFilePattern || `{model}/{name}.{type}.ts`,
);
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
let outputFilePattern = filenamify(configOutputFilePattern, {
replacement: '/',
})
.replace(/\.\./g, '/')
.replace(/\/+/g, '/');
outputFilePattern = trim(outputFilePattern, '/');
if (outputFilePattern !== configOutputFilePattern) {
$warnings.push(
`Due to invalid filepath 'outputFilePattern' changed to '${outputFilePattern}'`,
);
}
if (config.reExportAll) {
$warnings.push(`Option 'reExportAll' is deprecated, use 'reExport' instead`);
if (toBoolean(config.reExportAll)) {
config.reExport = 'All';
}
}
const fields: Record<string, ConfigFieldSetting | undefined> = Object.fromEntries(
Object.entries<Dictionary<string | undefined>>(
(config.fields ?? {}) as Record<string, Dictionary<string | undefined>>,
)
.filter(({ 1: value }) => typeof value === 'object')
.map(([name, value]) => {
const fieldSetting: ConfigFieldSetting = {
arguments: [],
output: toBoolean(value.output),
input: toBoolean(value.input),
model: toBoolean(value.model),
from: value.from,
defaultImport: toBoolean(value.defaultImport) ? true : value.defaultImport,
namespaceImport: value.namespaceImport,
};
return [name, fieldSetting];
}),
);
const decorate: DecorateElement[] = [];
const configDecorate: (Record<string, string> | undefined)[] = Object.values(
(config.decorate as any) || {},
);
for (const element of configDecorate) {
if (!element) continue;
ok(
element.from && element.name,
`Missed 'from' or 'name' part in configuration for decorate`,
);
decorate.push({
isMatchField: outmatch(element.field, { separator: false }),
isMatchType: outmatch(element.type, { separator: false }),
from: element.from,
name: element.name,
namedImport: toBoolean(element.namedImport),
defaultImport: toBoolean(element.defaultImport) ? true : element.defaultImport,
namespaceImport: element.namespaceImport,
arguments: element.arguments ? JSON5.parse(element.arguments) : undefined,
});
}
return {
outputFilePattern,
tsConfigFilePath: createTsConfigFilePathValue(config.tsConfigFilePath),
combineScalarFilters: toBoolean(config.combineScalarFilters),
noAtomicOperations: toBoolean(config.noAtomicOperations),
reExport: (ReExport[String(config.reExport)] || ReExport.None) as ReExport,
emitSingle: toBoolean(config.emitSingle),
emitCompiled: toBoolean(config.emitCompiled),
$warnings,
fields,
purgeOutput: toBoolean(config.purgeOutput),
useInputType: createUseInputType(config.useInputType as any),
noTypeId: toBoolean(config.noTypeId),
requireSingleFieldsInWhereUniqueInput: toBoolean(
config.requireSingleFieldsInWhereUniqueInput,
),
graphqlScalars: (config.graphqlScalars || {}) as Record<
string,
ImportNameSpec | undefined
>,
decorate,
};
}
Example #22
Source File: object-settings.ts From prisma-nestjs-graphql with MIT License | 4 votes |
function createSettingElement({
line,
config,
fieldElement,
match,
}: {
line: string;
config: GeneratorConfiguration;
fieldElement: ObjectSetting;
match: RegExpExecArray | null;
}) {
const result = {
documentLine: '',
element: undefined as ObjectSetting | undefined,
};
if (line.startsWith('@deprecated')) {
fieldElement.arguments!['deprecationReason'] = trim(line.slice(11));
result.element = fieldElement;
return result;
}
const name = match?.groups?.name;
if (!(match && name)) {
result.documentLine = line;
return result;
}
const element: ObjectSetting = {
kind: 'Decorator',
name: '',
arguments: [],
input: false,
output: false,
model: false,
from: '',
};
result.element = element;
if (name === 'TypeGraphQL.omit' || name === 'HideField') {
Object.assign(element, hideFieldDecorator(match));
return result;
}
if (['FieldType', 'PropertyType'].includes(name) && match.groups?.args) {
const options = customType(match.groups.args);
merge(element, options.namespace && config.fields[options.namespace], options, {
kind: name,
});
return result;
}
if (name === 'ObjectType' && match.groups?.args) {
element.kind = 'ObjectType';
const options = customType(match.groups.args) as Record<string, unknown>;
if (typeof options[0] === 'string' && options[0]) {
options.name = options[0];
}
if (isObject(options[1])) {
merge(options, options[1]);
}
element.arguments = {
name: options.name,
isAbstract: options.isAbstract,
};
return result;
}
if (name === 'Directive' && match.groups?.args) {
const options = customType(match.groups.args);
merge(element, { model: true, from: '@nestjs/graphql' }, options, {
name,
namespace: false,
kind: 'Decorator',
arguments: Array.isArray(options.arguments)
? options.arguments.map(s => JSON5.stringify(s))
: options.arguments,
});
return result;
}
const namespace = getNamespace(name);
element.namespaceImport = namespace;
const options = {
name,
arguments: (match.groups?.args || '')
.split(',')
.map(s => trim(s))
.filter(Boolean),
};
merge(element, namespace && config.fields[namespace], options);
return result;
}