Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use .js extensions for imports to so that source is ESM #1519

Merged
merged 29 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0555624
Use .js
keller-mark May 2, 2023
10d0e89
Comments
keller-mark May 2, 2023
16ed22a
Revert webpack plugin
keller-mark May 2, 2023
8882c6e
Update cypress e2e tests
keller-mark May 2, 2023
b3a0305
Add/move dev-docs
keller-mark May 3, 2023
6d4445a
Update design-guidelines.md
keller-mark May 4, 2023
64f6010
Fix meta-updater
keller-mark May 4, 2023
23a3282
Revert config
keller-mark May 4, 2023
0b0b0f7
Update design-guidelines.md
keller-mark May 10, 2023
c343a02
Update README.md
keller-mark May 10, 2023
c41b292
Update design-guidelines.md
keller-mark May 10, 2023
45936c2
Update design-guidelines.md
keller-mark May 10, 2023
69bc990
Update design-guidelines.md
keller-mark May 10, 2023
26a569f
Update rollup.config.js
keller-mark May 10, 2023
1021dd6
Revert unrelated change
keller-mark May 10, 2023
e034cb4
Merge
keller-mark May 10, 2023
ad7e1f9
WIP: clean up lodash, mui, uuid imports
keller-mark May 10, 2023
457f319
More import fixes
keller-mark May 10, 2023
eef9a3a
De-duplicate imports
keller-mark May 10, 2023
2f637fd
Dev-docs about js imports
keller-mark May 10, 2023
e68bf20
Use publint
keller-mark May 10, 2023
1f84cfe
Merge
keller-mark May 10, 2023
0e1f343
isEqual
keller-mark May 10, 2023
3e9602c
Fix tests
keller-mark May 10, 2023
8c643a6
Merge branch 'keller-mark/zod' of github.com:vitessce/vitessce into k…
keller-mark May 10, 2023
226dc6d
Dev-docs
keller-mark May 10, 2023
512964a
Dev-docs linked from main README
keller-mark May 11, 2023
573ad26
Demo
keller-mark May 11, 2023
c5c7ddf
Feedback
keller-mark May 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
25 changes: 14 additions & 11 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
# References:
# - https://typescript-eslint.io/getting-started/#step-2-configuration
# - https://stackoverflow.com/a/75108187
root: true
parser: '@typescript-eslint/parser'
extends:
- eslint:recommended
- plugin:require-extensions/recommended
- plugin:react/recommended
- plugin:react-hooks/recommended
- plugin:cypress/recommended
- airbnb
- plugin:jsx-a11y/recommended
plugins:
- '@typescript-eslint'
- require-extensions
- react
- react-hooks
- cypress
- react-refresh
- import
- jsx-a11y
settings:
react:
version: detect
Expand All @@ -27,30 +34,26 @@ rules:
react/jsx-one-expression-per-line: [0] # Makes punctuation after tab awkward.
react/prop-types: [0] # Re-enable: https://github.com/vitessce/vitessce/issues/144
react/require-default-props: [0]
import/prefer-default-export: [0] # Hit eslint error: SyntaxError: Unexpected token, expected {
react/react-in-jsx-scope: [0]
react/jsx-curly-newline: [0]
react/jsx-no-bind: [0] # Allow passing functions as JSX props
import/no-extraneous-dependencies: [1]
react/jsx-props-no-multi-spaces: [0]
no-plusplus: [0]
react-refresh/only-export-components: [2, { "checkJS": true }]
import/no-duplicates: [2]
overrides:
- files: 'sites/docs/src/theme/**'
- files: 'sites/docs/src/{pages,theme}/**'
rules:
# Allow @theme/ and @docusaurus/ imports
import/no-unresolved: [0]
- files: 'sites/docs/src/pages/**'
rules:
# Allow @theme/ and @docusaurus/ imports
import/no-unresolved: [0]

#import/no-unresolved: [0]
#import/extensions: [0]
'@typescript-eslint/no-var-requires': [0]
no-undef: [0]
- files: '**/*.{ts,tsx}'
extends:
- plugin:@typescript-eslint/eslint-recommended
- plugin:@typescript-eslint/recommended
rules:
# Allow importing js/ts files without extension
import/no-unresolved: [0]
import/extensions: [0]

2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ jobs:
env:
NODE_OPTIONS: ${{ steps.get-options.outputs.node-options }}
- run: ./test.sh --action
- run: pnpm run bundle:ci
- run: pnpm run publint

test-e2e-demo:
runs-on: ubuntu-20.04
Expand Down
7 changes: 3 additions & 4 deletions .meta-updater/main.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import fs from 'node:fs';
import path from 'node:path';
import jsonDiff from 'json-diff-ts';
import lodash from 'lodash';
const { cloneDeep } = lodash;
import { cloneDeep } from 'lodash-es';

const isDryrun = process.env.META_UPDATER_MODE === 'dryrun';
const isVersionOnly = process.env.META_UPDATER_MODE === 'versiononly';
Expand All @@ -13,10 +12,10 @@ const DECKGL_VERSION = '~8.8.6';
const TURF_VERSION = "^6.5.0";
const NEBULAGL_VERSION = "0.23.8";
const OTHER_VERSIONS = {
'lodash': '^4.17.21',
'lodash-es': '^4.17.21',
'react-grid-layout-with-lodash': '^1.3.5',
"internmap": "^2.0.3",
"uuid": "^3.3.2",
"uuid": "^9.0.0",
"zarr": "0.5.1",
"zustand": "^3.5.10",
"@hms-dbmi/viv": "~0.13.7",
Expand Down
1 change: 1 addition & 0 deletions DEMOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,4 @@ Note that the S3 URLs contain the git hash, if you want to relate this to an exa
- 2023-02-01: [release-v2.0.3](https://s3.amazonaws.com/vitessce-data/demos/2023-02-01/f2ddf311/index.html)
- 2023-02-07: [release-v2.0.3](https://s3.amazonaws.com/vitessce-data/demos/2023-02-07/ca9494c3/index.html)
- 2023-03-24: [keller-mark/zod](https://s3.amazonaws.com/vitessce-data/demos/2023-03-24/28cbfd99/index.html)
- 2023-05-11: [keller-mark/file-exts](https://s3.amazonaws.com/vitessce-data/demos/2023-05-11/512964ad/index.html)
1 change: 1 addition & 0 deletions DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ Note that the S3 URLs contain the git hash, if you want to relate this to an exa
- 2023-02-01: [release-v2.0.3](http://vitessce-data.s3-website-us-east-1.amazonaws.com/docs/2023-02-01/f2ddf311/)
- 2023-02-07: [release-v2.0.3](http://vitessce-data.s3-website-us-east-1.amazonaws.com/docs/2023-02-07/ca9494c3/)
- 2023-03-24: [keller-mark/zod](http://vitessce-data.s3-website-us-east-1.amazonaws.com/docs/2023-03-24/28cbfd99/)
- 2023-05-11: [keller-mark/file-exts](http://vitessce-data.s3-website-us-east-1.amazonaws.com/docs/2023-05-11/512964ad/)
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pnpm run start-demo

The development server will refresh the browser as you edit the code.

Further details for internal developers can be found within [dev-docs](./dev-docs/).

### Branches

Please use one of the following naming conventions for new branches:
Expand Down Expand Up @@ -91,6 +93,14 @@ pnpm run build-demo
- To run all the tests, both unit and e2e: `./test.sh`
- To run just the unit tests: `pnpm run test`

### Linting

```sh
pnpm run lint
```

To allow the linter to perform automated fixes during linting: `pnpm run lint-fix`

### Troubleshooting

The following commands can be helpful in case the local environment gets into a broken state:
Expand Down
31 changes: 31 additions & 0 deletions dev-docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Developer documentation

The developer documentation here is meant for usage by the internal development team, external contributors, and plugin developers.

## For plugin developers

- [View type implementation](./plugin-view-types.md)
- [File type implementation](./plugin-file-types.md)

## For internal developers

We not only want to document implementation details, but also higher-level architectural details and development processes.
However, documentation that would be relevant to a wider audience than noted above should instead be included in the main documentation website that is hosted at http://vitessce.io.

### Architecture

The diagram below highlights how Vitessce is composed of a top-level `<Vitessce/>` React component which encapsulates several individual visualization or control views such as `<Scatterplot/>` and `<Spatial/>`.

<a href="https://docs.google.com/drawings/d/1vS6wP1vs5QepLhXGDRww7LR505HJ-aIqnGn9O19f6xg/edit" target="_blank">
<img
src="https://docs.google.com/drawings/d/e/2PACX-1vSoB3YGPxOTKnFOpYHeHX4JruHnibGXruM36uAZtuvPQNM3a7F4uS3q4b5jwGNQ6TJ7bQ9IPB32rdle/pub?w=650"
alt="Architecture diagram"
className="ar-16x9"
/>
</a>

### Table of contents

- [Design guidelines](./design-guidelines.md)
- [Monorepo and bundling](./monorepo-and-bundling.md)
- [Config schema versioning](./config-schema-versioning.md)
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
---
id: dev-config-versioning
title: Config schema versioning
---
# Config schema versioning

## Motivation

Expand All @@ -26,4 +23,4 @@ A new config schema version should be added when:

Config schemas are defined using [Zod](https://zod.dev/) in the `@vitessce/schemas` sub-package of the Vitessce monorepo.

See the [README](https://github.com/vitessce/vitessce/tree/main/packages/schemas/README.md) for detailed instructions.
See the [README](../packages/schemas/README.md) for detailed instructions.
34 changes: 34 additions & 0 deletions dev-docs/design-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ An evolving set of guidelines to ensure that features remain maintainable, scala

## Design Guidelines

### User experience decisions
- When making decisions that affect user experience, prefer [consistency](http://vis.pku.edu.cn/research/publication/consistency.pdf).

### Tests

- Prefer unit tests over end-to-end tests - Keep React components relatively "dumb" and put complex logic into utility functions that can be easily unit-tested.
- Test in [portal-ui](https://github.com/hubmapconsortium/portal-ui) with diverse data modalities prior to major releases

### Data types

Expand All @@ -22,4 +26,34 @@ An evolving set of guidelines to ensure that features remain maintainable, scala

- Avoid [circular dependencies](https://github.com/vitessce/vitessce/issues/1490) - If you find the need to import functions across view type- or file type- sub-packages, consider moving to a utility sub-package (i.e., `packages/utils/`).
- Avoid complex dependencies in utility sub-packages - Where possible keep dependencies in utility sub-packages small and simple (e.g., `lodash`). If a large/complex dependency is needed for a utility function, consider refactoring that function into a new utility sub-package.

### TypeScript

- Implement new sub-packages using TypeScript to avoid creating tech debt.

### Parsing and validation of user input
- Prefer [Zod](https://zod.dev/) schema over JSON schema - This improves the TypeScript development experience and follows the ["parse, don't validate"](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/) mantra.

### Coordination type schemas
- Prefer primitive values like numbers and strings over objects and arrays - Coordination values must be used entirely. Therefore, usage of objects and arrays prevent linking views on a subset of the object/array values.


## Code style guide

> A good style guide defines not only superficial elements like naming conventions or whitespace rules but also how to use the features of the given programming language. JavaScript and Perl, for example, are packed with functionality — they offer many ways to implement the same logic. A style guide defines The One True Way of doing things so that you don’t end up with half your team using one set of language features while the other half uses a totally different set of features. -- [How to Do Code Reviews Like a Human](https://mtlynch.io/human-code-reviews-1/).

This section contains an evolving set of code style guidelines that are not currently automated via linting.

- Use MUI style utilities to define styles ([makeStyles](https://v4.mui.com/styles/api/#makestyles-styles-options-hook), at least until we migrate to MUI v5).
- Use `false`, `null`, and `undefined` as false-y values unless the corresponding truth-y value is a number (to align with [JSX boolean handling](https://legacy.reactjs.org/docs/jsx-in-depth.html#booleans-null-and-undefined-are-ignored)).
- Use `lodash/isEqual` for set path equality checks and comparisons.
- Prefer more specific naming for utility functions (despite length/verbosity) to help readability.
- Prefer event handlers to side effects (from React docs: [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect))
- Related: exercise caution when removing effect dependencies (from React docs: [Removing Effect Dependencies](https://react.dev/learn/removing-effect-dependencies))
- Web workers should be [inlined](../packages/workers/rollup.config.js) so that they do not depend on relative paths that consumer applications and libraries would need to configure.
- Use `.js` extensions for relative imports, [even in TypeScript contexts](https://github.com/microsoft/TypeScript/issues/42151#issuecomment-914472944).
- Do not use `.js` extensions for third-party packages, unless either:
- The function or variable that needs to be accessed is not exported from the main entrypoint of the package.
- The package is published as CommonJS or UMD rather than ESM (or the ESM build is broken as with [json2csv](https://github.com/zemirco/json2csv/issues/539) and [react-virtualized](https://github.com/bvaughn/react-virtualized/issues/1632)).


File renamed without changes.
2 changes: 0 additions & 2 deletions dev-docs/monorepo-and-bundling.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ It contains:
- `sites/html`: A plain HTML page that imports sub-packages for testing.
- `examples/`: packages that consume the sub-packages but are just used internally (e.g., for the demo or docs web apps; not published to NPM)

These are also specified in `pnpm-workspace.yaml` to let PNPM know which subdirectories contain packages.

## Code transformation

This monorepo organization has implications for how code is "transformed".
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
---
id: dev-add-loader
title: File type implementation
---
# File type implementation

In order to load data from a particlar **file type**, two classes must be implemented: a _data loader_ class and a _data source_ class.

## The data loader class

Each data loader class should inherit from [`AbstractTwoStepLoader`](https://github.com/vitessce/vitessce/blob/main/src/loaders/AbstractTwoStepLoader.js) which has two constructor parameters:
Each data loader class should inherit from [`AbstractTwoStepLoader`](../packages/vit-s/src/data/AbstractTwoStepLoader.js) which has two constructor parameters:

- `dataSource` (`any`) - A data source instance. See the [data source](#the-data-source) section below.
- `fileDef` (`object`) - A file definition from view config `datasets[].files[]`.
Expand All @@ -22,7 +19,7 @@ Each loader class must implement its own `load()` method.

### The `load()` return value

The `load()` method should return a promise that resolves to a [`LoaderResult`](https://github.com/vitessce/vitessce/blob/main/src/loaders/LoaderResult.js) instance.
The `load()` method should return a promise that resolves to a [`LoaderResult`](../packages/vit-s/src/data/LoaderResult.js) instance.

Depending on the **data type** of the **file type**, the `data` parameter of the `LoaderResult` constructor should be a JS object with the following structure:

Expand Down Expand Up @@ -70,10 +67,10 @@ class MyLoader extends AbstractTwoStepLoader {

## The file type registry

Similar to the [view type registry](/docs/dev-add-component/#the-view-type-registry), there must be a mapping between a **file type** name and the actual data loader & data source class definitions to facilitate usage of the file type name as a string ([`datasets[].files[].fileType`](/docs/view-config-json/#datasets)) in the JSON view config.
The [file type registry](https://github.com/vitessce/vitessce/blob/main/src/loaders/types.js) maps file types to `[data source, data loader]` tuples.
Every file type in the registry must be [mapped to a data type](https://github.com/vitessce/vitessce/blob/main/src/app/constant-relationships.js) as well.
Similar to the [view type registry](./plugin-view-types.md#the-view-type-registry), there must be a mapping between a **file type** name and the actual data loader & data source class definitions to facilitate usage of the file type name as a string (`datasets[].files[].fileType`) in the JSON view config.
The [file type registry](../packages/main/all/src/base-plugins.ts) maps file types to `[data source, data loader]` tuples.
Every file type in the registry must be [mapped to a data type](../packages/constants-internal/src/app/constant-relationships.js) as well.

:::tip
The plugin analog of the file type registry is the [`registerPluginFileType`](/docs/dev-plugins/#plugin-file-types) function.
The plugin analog of the file type registry is the [`pluginFileTypes`](/docs/dev-plugins/#plugin-file-types) prop.
:::
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
---
id: dev-add-component
title: View type implementation
---
# View type implementation

This page walks through the steps required to create a new visualization component.
Vitessce components are React components which conform to certain conventions, and may be implemented with libraries such as Vega-Lite, D3, DeckGL or plain JavaScript code.
Expand All @@ -12,9 +9,9 @@ All of the core Vitessce components consist of at least two React components: an
By convention, we add the suffix `Subscriber` to the name of the parent component.

The parent ("subscriber") component typically carries out the following:
- get and set values from the coordination space with the [`useCoordination`](https://github.com/vitessce/vitessce/blob/main/packages/vit-s/src/app/state/hooks.js#L196) hook function.
- should render the [`TitleInfo`](https://github.com/vitessce/vitessce/blob/main/packages/vit-s/src/TitleInfo.js) component as a parent of its "plain" component.
- load data from files specified in the view config with [data hook](https://github.com/vitessce/vitessce/blob/main/packages/vit-s/src/data-hooks.js) functions.
- get and set values from the coordination space with the [`useCoordination`](../packages/vit-s/src/app/state/hooks.js#L196) hook function.
- should render the [`TitleInfo`](../packages/vit-s/src/TitleInfo.js) component as a parent of its "plain" component.
- load data from files specified in the view config with [data hook](../packages/vit-s/src/data-hooks.js) functions.

A React subtree for a component called `FeatureListSubscriber` would look like:

Expand All @@ -26,7 +23,7 @@ A React subtree for a component called `FeatureListSubscriber` would look like:
</FeatureListSubscriber>
```

A full example of a parent component can be found in [FeatureListSubscriber](https://github.com/vitessce/vitessce/blob/main/packages/view-types/feature-list/src/FeatureListSubscriber.js).
A full example of a parent component can be found in [FeatureListSubscriber](../packages/view-types/feature-list/src/FeatureListSubscriber.js).

:::note
The usage of the term "subscriber" here comes from prior usage of a pub-sub pattern in Vitessce. Now we use the `[values, setters]` returned by the custom `useCoordination` hook to manage state in a more `React.useState`-like pattern (instead of pub-sub).
Expand All @@ -36,7 +33,7 @@ The usage of the term "subscriber" here comes from prior usage of a pub-sub patt

The child component may take data and callback functions as props from its parent subscriber function, and should use its props to render a visualization or controller component. The plain component should not use the `useCoordination` hook or any of the `use___Data` hook functions.

A full example of a child component can be found in [FeatureList](https://github.com/vitessce/vitessce/blob/main/packages/view-types/feature-list/src/FeatureList.js).
A full example of a child component can be found in [FeatureList](../packages/view-types/feature-list/src/FeatureList.js).

:::note
In theory, we could perform both the parent- and child-component tasks in one component.
Expand All @@ -46,17 +43,17 @@ Making the child component agnostic to the state management and data loading imp

## The view type registry

There must be a mapping between a **view type** name and the actual React component function to facilitate usage of the view type as a string ([`layout[].component`](/docs/view-config-json/#layout)) in the JSON view config. The [view type registry](https://github.com/vitessce/vitessce/tree/main/packages/main/all/src) maps view types to JavaScript functions.
There must be a mapping between a **view type** name and the actual React component function to facilitate usage of the view type as a string (`layout[].component`) in the JSON view config. The [view type registry](../packages/main/all/src/base-plugins.ts) maps view types to JavaScript functions.

:::tip
The plugin analog of the view type registry is the [`registerPluginViewType`](/docs/dev-plugins/#plugin-view-types) function.
The plugin analog of the view type registry is the `pluginViewTypes` prop.
:::

## Component coordination types

In order for a component to access or change values in the coordination space, the mapping from the view type name to a subset of coordination types must be defined in [`COMPONENT_COORDINATION_TYPES`](https://github.com/vitessce/vitessce/blob/main/packages/vit-s/src/app/state/coordination.js).
In order for a component to access or change values in the coordination space, the mapping from the view type name to a subset of coordination types must be defined in [`COMPONENT_COORDINATION_TYPES`](../packages/vit-s/src/app/state/coordination.js).
This helps to avoid unnecessary component re-rendering events (i.e., if we know that the heatmap does not depend on the `spatialZoom` coordination type, we can omit this from the list of coordination types used by the heatmap component, and the heatmap will not re-render upon `spatialZoom` updates).

:::tip
The plugin analog of `COMPONENT_COORDINATION_TYPES` is the `coordinationTypes` parameter of the [`registerPluginViewType`](/docs/dev-plugins/#plugin-view-types) function.
The plugin analog of `COMPONENT_COORDINATION_TYPES` is the `coordinationTypes` parameter of the `PluginViewType` constructor.
:::