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 vote down vote up
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 vote down vote up
/**
 * 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 vote down vote up
@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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
trim(): Str {
        return Str.from(trim(`${this}`));
    }
Example #13
Source File: bot.ts    From Adachi-BOT with MIT License 5 votes vote down vote up
/* 正则检测处理消息 */
	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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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;
}