question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Umbrella] Updating & Fixing Types

See original GitHub issue

☔️ Overview

Doing a clean up round on types, using this issue to track the PR’s associated to it.Will be editing this post as I progress. Comments/Recommendations are appreciated.

First Round

First Round will be small isolated PR’s, that way no conflicting discussions or delays in certain scope effects the initiation of Second Round Changes.

  • jest-config (getMaxWorkers) #8434

    • Missing type string when getMaxWorkers allows a string
  • jest-validate (condition)- multipleValidOptions #8435

    • should infer the types of its arguments, and return a union type of the types
  • jest-config (utils) #8437

    • Improve/Fix typing’s
    • potentially merge _replaceRootDirInObject within _replaceRootDirTags
  • jest-config(normalize)

    • Improve typing’s of main normalize function and helpers (not changing code eval)
  • jest-types

    • Use interfaces where makes sense in-order to merge/extends easier
    • Maybe: Add a separate interface for “deprecated options” that are still supported
  • jest-enviroment #8439

    • Add types to ModuleWrapper
    • Update usage in jest-runtime
  • General Maintenance #8462

    • Remove/Fix unnecessary castings
    • make all general Object Types consistent throughout the codebase, using Record.

Second Round

Second Round will begin after key PRs(dependable) from first round are committed.

  • jest-config(normalize) - Improve typing’s and structure
    • Current structure of the normalize function is not type-safe and can be optimized. ( hold off in favor of #7185 )

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:10
  • Comments:12 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
JoshRosensteincommented, May 8, 2019

@jeysal , that makes sense. and in that case i will hold off on any dramatic changes on normalize. On a related note,I was trying to think of a way to re-format jest-types Config, and this may also be helpful when restructuring the way the configs are handled. With the current state of Config types, i was trying to think of a way to break down the types and reuse them throughout the main exports InitialOptions,DefaultOptions ,GlobalConfig ProjectConfig Argv. Rather than the current setup of having all properties repeatedly typed. So I began with partitioning the overlaps of GlobalConfig ProjectConfig Argv, and treated the properties as a pipe line from argv. and came up with something like this: *“Shared” refers to ProjectConfig & GlobalConfig Looking at ProjectConfig First, what properties types on Argv, are identical to the required ProjectConfig, (will call this Direct)

/** Argv Options That share same type as Project Options*/
export interface ArgvToProjectDirect {
  automock: boolean;
  browser: boolean;
  cache: boolean;
  cacheDirectory: Path;
  clearMocks: boolean;
  moduleDirectories: Array<string>;
  moduleFileExtensions: Array<string>;
  modulePathIgnorePatterns: Array<string>;
  modulePaths: Array<string>;
  preset: string | Nil;
  prettierPath: string;
  resetMocks: boolean;
  resetModules: boolean;
  resolver: Path | Nil;
  restoreMocks: boolean;
  roots: Array<Path>;
  setupFiles: Array<Path>;
  setupFilesAfterEnv: Array<Path>;
  snapshotSerializers: Array<Path>;
  testEnvironment: string;
  testPathIgnorePatterns: Array<string>;
  testRunner: string;
  testURL: string;
  transformIgnorePatterns: Array<Glob>;
  unmockedModulePathPatterns: Array<string> | Nil;
  watchPathIgnorePatterns: Array<string>;
}
}

⬇️ Next what are the properties that share the same key but undlerying types are different. ( will break this down into 2 Raw & derivedfromArgv.

/** Argv Options needed for Project Options that require manipulation*/
export interface ArgvToProjectRaw {
  globals: string;
  haste: string;
  moduleNameMapper: string;
  testRegex: string | Array<string>;
  timers: string;
  transform: string;
}

/** The Project Options Derived from Argv Options */
export interface ProjectOptionsDerivedFromArgv {
  globals: ConfigGlobals;
  haste: HasteConfig;
  moduleNameMapper: Array<[string, string]>;
  testRegex: Array<string>;
  timers: 'real' | 'fake';
  transform: Array<[string, Path]>;
}

⬇️ Next the remaining ProjectOptions that are derived elsewhere or in combination of other options, (will call this ProjectOptionsDerived)

export interface ProjectOptionsDerived {
  cwd: Path;
  dependencyExtractor?: string;
  displayName?: DisplayName;
  forceCoverageMatch: Array<Glob>;
  moduleLoader: Path;
  name: string;
  runner: string;
  skipFilter: boolean;
  skipNodeResolution: boolean;
  snapshotResolver: Path | Nil;
  testEnvironmentOptions: Record<string, any>;
  testLocationInResults: boolean;
}

Now do the same for GlobalConfig

/** The Argv Options shared to directly to global */
export interface ArgvToGlobalDirect {
  changedFilesWithAncestor: boolean;
  changedSince: string;
  collectCoverage: boolean;
  coverageDirectory: string;
  findRelatedTests: boolean;
  forceExit: boolean;
  json: boolean;
  lastCommit: boolean;
  logHeapUsage: boolean;
  maxWorkers: number;
  noStackTrace: boolean;
  notify: boolean;
  onlyChanged: boolean;
  projects: Array<Glob>;
  silent: boolean;
  testMatch: Array<Glob>;
  testNamePattern: string;
  testResultsProcessor: string | Nil;
  testSequencer: string;
  useStderr: boolean;
  verbose: boolean | Nil;
  watch: boolean;
  watchAll: boolean;
  watchman: boolean;
}

/** Argv Options needed for Global Options that require manipulation*/
export interface ArgvToGlobalRaw {
  bail: boolean | number;
  collectCoverageFrom: string;
  collectCoverageOnlyFrom: Array<string>;
  coverageReporters: Array<string>;
  coverageThreshold: string;
  outputFile: Path;
  testPathPattern: Array<string>;
  testFailureExitCode: string | Nil;
  notifyMode: string;
  updateSnapshot: boolean;
}

/** The Global Options Derived from Argv Options */
export interface GlobalOptionsDerivedFromArgv {
  bail: number;
  collectCoverageFrom: Array<Glob>;
  collectCoverageOnlyFrom: {[key: string]: boolean} | Nil;
  coverageReporters: Array<ReportOptionKeys>;
  coverageThreshold: CoverageThreshold;
  expand: boolean;
  notifyMode: NotifyMode;
  outputFile: Path | Nil;
  testFailureExitCode: number;
  testPathPattern: string;
  updateSnapshot: SnapshotUpdateState;
}

/** Derived Global Options*/
export interface GlobalOptionsDerived {
  enabledTestsMap: {[key: string]: {[key: string]: boolean}} | Nil;
  forceExit: boolean;
  listTests: boolean;
  maxConcurrency: number;
  noSCM: boolean | Nil;
  nonFlagArgs: Array<string>;
  onlyFailures: boolean;
  passWithNoTests: boolean;
  replname: string | Nil;
  reporters: Array<string | ReporterConfig>;
  runTestsByPath: boolean;
  skipFilter: boolean;
  watchPlugins: Array<{path: string; config: Record<string, any>}> | Nil;
}

Then again for options that are shared b/n global and project

/** Argv Options That share same type as Shared Project & Global Options */
export interface ArgvToSharedDirect {
  coveragePathIgnorePatterns: Array<string>; // Global has optional
  globalSetup: string | Nil;
  globalTeardown: string | Nil;
  rootDir: Path;
}

/** Argv Options needed for Project & Global Options that require manipulation*/
export interface ArgvToSharedRaw {}

/** Shared Project & Global Options Derived from Argv Options */
export interface SharedOptionsDerivedFromArgv {}

/** Derived Options that are shared b/n Global and Project*/
export interface SharedOptionsDerived {
  detectLeaks: boolean;
  detectOpenHandles: boolean;
  errorOnDeprecated: boolean;
  extraGlobals: Array<keyof NodeJS.Global>; /// GlobalConfig has string[]
  filter: Path | Nil;
}

Now defining the remaining argv config that doesnt get passed on

/** Argv Options That dont share same config names*/
export interface ArgvCustom {
  /** This Option Does...*/
  all: boolean;
  ci: boolean;
  clearCache: boolean;
  color: boolean;
  colors: boolean;
  config: string;
  coverage: boolean;
  debug: boolean;
  env: string;
  init: boolean;
  runInBand: boolean;
  showConfig: boolean;
  version: boolean;
}

Then the final resulting types:

export interface ArgVRaw
  extends ArgvCustom,
    ArgvToGlobalRaw,
    ArgvToGlobalDirect,
    ArgvToSharedDirect,
    ArgvToSharedRaw,
    ArgvToProjectDirect,
    ArgvToProjectRaw {}

export type Argv = Arguments<Partial<ArgVRaw>>;
export interface SharedOptions
  extends SharedOptionsDerived,
    SharedOptionsDerivedFromArgv,
    ArgvToSharedDirect {}

export interface SharedOptions
  extends SharedOptionsDerived,
    SharedOptionsDerivedFromArgv,
    ArgvToSharedDirect {}

export interface GlobalOptions
  extends SharedOptions,
    GlobalOptionsDerived,
    GlobalOptionsDerivedFromArgv,
    ArgvToGlobalDirect {}

export interface ProjectOptions
  extends SharedOptions,
    ProjectOptionsDerived,
    ProjectOptionsDerivedFromArgv,
    ArgvToProjectDirect {}

export interface AllOptions extends GlobalOptions, ProjectOptions {}

export type AllOptionsPartial = Partial<AllOptions>;

export type AllOptionsNullable = {[P in keyof AllOptions]: AllOptions[P] | Nil};

// Allow Setting Default to Null ?
export type DefaultOptions = Partial<AllOptionsNullable>;

export type InitialOptions = AllOptionsPartial;

Breaking them down may also be helpful with functional transformers:

const someTransformer= (input:ArgvToProjectRaw):ProjectOptionsDerivedFromArgv=>...

And you will also be able to write option api description once and keep intelli throughout. config_intelli

lmk your thoughts… i’ll tinker around a bit. (btw sorry for the long tangent)

1reaction
jeysalcommented, May 7, 2019

@JoshRosenstein My preference would be to validate user-provided config using io-ts. Then, once we’ve ensured that the objects we’re operating on actually match our static types exactly, we should generate the internal config format in a way that typechecks well (e.g. avoiding mutation in favour of a more functional style usually helps with this). To be clear, I still see the need to treat user config and internal config separately. One reason for this is that internal config usually has goals like not being redundant (e.g. you shouldn’t need to both check for undefined and '' on the config unless there’s a semantic difference), while user config might not care about this and offer alternatives (e.g. shortening an array containing a single string to just a string) - these are just examples. Simplifying configuration is scheduled for v25, yes. I expect normalize to be mostly rewritten in the process (kind of scared how this will play with not reworking CLI options at the same time though), so I think the easiest way of going about it would be to just ensure that the new code is TSC-friendly.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Prerequisites - Cisco Umbrella Documentation
To ensure that the Cisco Umbrella roaming client deploys and runs successfully, Umbrella requires that you meet the following prerequisites.
Read more >
How To Fix The SSH Key Vulnerability In Cisco Umbrella ...
Upgrading Cisco Umbrella to v3.3.2 is the recommended approach to fix the SSH Key vulnerability in Cisco Umbrella Virtual Appliance. Let's see how...
Read more >
thi-ng/umbrella: Broadly scoped ecosystem & mono ... - GitHub
Immutable data handling, state containers, transacted state updates, Undo-Redo history; Data driven UI component toolkits (DOM-based, canvas-based, immediate- ...
Read more >
Cisco ASA Series Firewall CLI Configuration Guide, 9.13 ...
This allows Cisco Umbrella to identify requests to black- or grey-list domain names and apply your DNS-based security policy.
Read more >
Neewer® 2 Pieces S-Type Bracket Holder with Bowens Mount ...
Amazon.com : Neewer® 2 Pieces S-Type Bracket Holder with Bowens Mount for Speedlite Flash Snoot Softbox Beauty Dish Reflector Umbrella : Electronics.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found