atlassian-labs / compiled

A familiar and performant compile time CSS-in-JS library for React.
https://compiledcssinjs.com
Apache License 2.0
1.98k stars 68 forks source link

Throw clearer error when object property name is imported through barrel files #1606

Open dddlr opened 8 months ago

dddlr commented 8 months ago

Imagine we have a project with the following code:

////////////////////////
// constants.ts
////////////////////////

export const UNSAFE_container = {
    below: {
        xs: "@container not all and (min-width: 30rem)",
        sm: "@container not all and (min-width: 48rem)",
        md: "@container not all and (min-width: 64rem)",
        lg: "@container not all and (min-width: 90rem)",
        xl: "@container not all and (min-width: 110rem)"
    }
};

////////////////////////
// index.ts
////////////////////////

export * from './constants';

////////////////////////
// some_other_file.ts
////////////////////////

import { UNSAFE_container } from './index';
import { css } from '@compiled/react';

<div css={
    css({ [UNSAFE_container.below.xs]: ... })
}>
    hello world
</div>

Here, index.ts is acting as a barrel file, re-exporting an already exported constant.

This cannot be statically evaluated by @compiled/babel-plugin, and thus we get an error (Cannot statically evaluate the value of "MemberExpression)

Ideally, we should provide a more descriptive error than this that provides some actionable information. For example:

Compiled cannot determine the value of `UNSAFE_container.below.xs` at build time. There are many reasons why this might happen:

* Use of barrel files [insert description of what a barrel file is here]
* The value of `UNSAFE_container.below.xs` uses a syntax we don't support (e.g. `as const`)
* (etc etc......)

Ideally this message should address all the common things we can think of that @compiled/babel-plugin cannot statically analyse, not just barrel files.

dddlr commented 8 months ago

Also applies to this example: (I'm sure there are many others)

const UNSAFE_container = Object.freeze({
    below: {
        xs: "@container not all and (min-width: 30rem)",
        sm: "@container not all and (min-width: 48rem)",
        md: "@container not all and (min-width: 64rem)",
        lg: "@container not all and (min-width: 90rem)",
        xl: "@container not all and (min-width: 110rem)"
    }
});

const myStyles = css({
    [UNSAFE_container.below.xs]: ...
});

<div css={myStyles}>
    hello world
</div>