@yahoo/uds 0.1.14 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- package/cli/README.md +57 -5
- package/cli/commands/expo/_setup.ts +59 -15
- package/cli/commands/expo/build.ts +2 -1
- package/cli/commands/expo/dev.ts +17 -8
- package/cli/commands/expo/expo.ts +6 -6
- package/cli/commands/expo/launch.ts +1 -0
- package/cli/commands/expo/update.ts +1 -0
- package/cli/commands/purge.ts +16 -0
- package/cli/commands/{config/sync.ts → sync.ts} +3 -2
- package/cli/commands/uds.ts +1 -0
- package/cli/env.d.ts +3 -0
- package/cli/utils/configWorker.ts +23 -1
- package/cli/utils/getCommandHelp.ts +3 -4
- package/cli/utils/purgeCSS.ts +138 -0
- package/cli/utils/setupConfigWorker.ts +15 -18
- package/dist/{chunk-P7GR6E3K.js → chunk-AHFH5E5L.js} +1 -1
- package/dist/{chunk-MBOOJIH7.js → chunk-FLBMVDKG.js} +1 -1
- package/dist/{chunk-AWTLI4D3.js → chunk-U3UPAQ7V.js} +1 -1
- package/dist/fixtures/index.cjs +1 -1
- package/dist/fixtures/index.d.cts +1 -3
- package/dist/fixtures/index.d.ts +1 -3
- package/dist/fixtures/index.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +103 -32
- package/dist/index.d.ts +103 -32
- package/dist/index.js +1 -1
- package/dist/{index.native-9kYJrUPa.d.ts → index.native-fciGC1AQ.d.cts} +2 -2
- package/dist/{index.native-3ww4C4UV.d.cts → index.native-hIYZ_ma-.d.ts} +2 -2
- package/dist/index.native.cjs +1 -1
- package/dist/index.native.d.cts +10 -24
- package/dist/index.native.d.ts +10 -24
- package/dist/index.native.js +1 -1
- package/dist/tailwindPlugin.cjs +1 -1
- package/dist/tailwindPlugin.d.cts +1 -1
- package/dist/tailwindPlugin.d.ts +1 -1
- package/dist/tailwindPlugin.js +1 -1
- package/dist/tailwindPurge.cjs +4 -0
- package/dist/tailwindPurge.d.cts +16 -0
- package/dist/tailwindPurge.d.ts +16 -0
- package/dist/tailwindPurge.js +4 -0
- package/dist/tokens/index.cjs +1 -1
- package/dist/tokens/index.d.cts +3 -3
- package/dist/tokens/index.d.ts +3 -3
- package/dist/tokens/index.js +1 -1
- package/dist/tokens/index.native.cjs +1 -1
- package/dist/tokens/index.native.d.cts +2 -2
- package/dist/tokens/index.native.d.ts +2 -2
- package/dist/tokens/index.native.js +1 -1
- package/dist/tokens/parseTokens.cjs +1 -1
- package/dist/tokens/parseTokens.d.cts +12 -12
- package/dist/tokens/parseTokens.d.ts +12 -12
- package/dist/tokens/parseTokens.js +1 -1
- package/dist/tokens/parseTokens.native.d.cts +2 -2
- package/dist/tokens/parseTokens.native.d.ts +2 -2
- package/dist/{types-J4DLS6Xj.d.cts → types-3GXulqnG.d.cts} +1 -1
- package/dist/{types-J4DLS6Xj.d.ts → types-3GXulqnG.d.ts} +1 -1
- package/dist/{types-hirL9Qk5.d.cts → types-_E6o7OhU.d.cts} +47 -54
- package/dist/{types-hirL9Qk5.d.ts → types-_E6o7OhU.d.ts} +47 -54
- package/package.json +20 -4
- package/cli/commands/config/config.ts +0 -10
- package/cli/commands/nextjs/dev.ts +0 -17
- package/cli/commands/nextjs/nextjs.ts +0 -10
- package/cli/eslint.config.mjs +0 -8
package/cli/README.md
CHANGED
@@ -1,16 +1,68 @@
|
|
1
|
-
# UDS
|
1
|
+
# UDS Cli
|
2
2
|
|
3
3
|
We leverage Bluebun, which is a CLI framework inspired by [Gluegun](https://github.com/infinitered/gluegun), but specifically designed to be used with [Bun](https://bun.sh), the new JS runtime.
|
4
4
|
|
5
5
|
Bluebun relies on Bun APIs and is designed to be extremely fast, with no-dependencies.
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
We use Bun to build our standalone executable. See [Bun build docs](https://bun.sh/docs/bundler/executables) for more details. The uds package.json's `build:cli` script handles building the CLI. The bin is output to the `dist/uds` binary file and this path is defined in the package.json's bin field.
|
7
|
+
> Trying to add a new command? Please see the "Adding a Command" section below
|
10
8
|
|
11
9
|
# Commands
|
12
10
|
|
13
|
-
|
11
|
+
In any consumer of `@yahoo/uds` the following commands are available:
|
12
|
+
|
13
|
+
> Please note: If you are _not_ running the CLI from a package.json script you will need to add `bun` before the binary in order to run it directly. i.e. `bun uds purge`
|
14
|
+
|
15
|
+
## Config
|
16
|
+
|
17
|
+
### Using args
|
18
|
+
|
19
|
+
| Arg | Required | Default |
|
20
|
+
| ------- | -------- | --------------- |
|
21
|
+
| id | true | |
|
22
|
+
| outFile | false | ./uds.config.ts |
|
23
|
+
|
24
|
+
```shell
|
25
|
+
uds sync --id [id] --outFile [path]
|
26
|
+
```
|
27
|
+
|
28
|
+
```shell
|
29
|
+
uds sync --id [id]
|
30
|
+
```
|
31
|
+
|
32
|
+
### Using ENV vars
|
33
|
+
|
34
|
+
| Env Var | Required | Default |
|
35
|
+
| ------------ | -------- | --------------- |
|
36
|
+
| UDS_ID | true | |
|
37
|
+
| UDS_OUT_FILE | false | ./uds.config.ts |
|
38
|
+
|
39
|
+
```shell
|
40
|
+
UDS_ID=[id] uds sync --outFile [path]
|
41
|
+
```
|
42
|
+
|
43
|
+
```shell
|
44
|
+
UDS_ID=[id] UDS_OUT_FILE=[path] uds sync
|
45
|
+
```
|
46
|
+
|
47
|
+
## Expo
|
48
|
+
|
49
|
+
```shell
|
50
|
+
uds expo build --profile [profile] --platform [ios|android]
|
51
|
+
uds expo dev --profile [profile] --platform [ios|android]
|
52
|
+
uds expo launch --profile [profile] --platform [ios|android]
|
53
|
+
uds expo update --profile [profile] --platform [ios|android]
|
54
|
+
uds expo --help
|
55
|
+
```
|
56
|
+
|
57
|
+
## Purge CSS
|
58
|
+
|
59
|
+
```shell
|
60
|
+
uds purge
|
61
|
+
```
|
62
|
+
|
63
|
+
## Adding a command
|
64
|
+
|
65
|
+
> Please note: Adding nested commands, i.e. uds expo dev, appears to not work correctly when UDS is consumed from npm. As a workaround, please see code for expo/expo.ts for re-routing sub-commands from the root command file. To verify your CLI command works correctly you should run `npm pack` within the packages/uds directory. Once you have your generated tarball you should copy that tarball to a test application such as https://github.com/yahoo-design/uds-nextjs-demo, then add `"@yahoo/uds": "file:./tarball-generated-from-npm-pack.tgz` to it's dependencies and run an install. Now you should be able to run `bun uds [your command name]` to test your functionality.
|
14
66
|
|
15
67
|
Commands are organized in a tree structure. The root command is the name of the CLI (uds), and then we can have subcommands under that, and subcommands under those, and so on.
|
16
68
|
|
@@ -1,5 +1,8 @@
|
|
1
|
+
import fs from 'node:fs';
|
2
|
+
import os from 'node:os';
|
3
|
+
|
1
4
|
import { EasJsonAccessor, EasJsonUtils, Platform } from '@expo/eas-json';
|
2
|
-
import { type Props
|
5
|
+
import { print, type Props } from 'bluebun';
|
3
6
|
import { $, semver, which } from 'bun';
|
4
7
|
|
5
8
|
export interface MobileProps extends Props {
|
@@ -29,19 +32,60 @@ export async function setup({
|
|
29
32
|
const { profile, platform, jsEngine = 'hermes', debug = false } = props.options;
|
30
33
|
const isIOS = platform === Platform.IOS;
|
31
34
|
const isAndroid = platform === Platform.ANDROID;
|
35
|
+
const pathAsString = await $`echo $PATH`.text();
|
36
|
+
const needsBunInPath = !pathAsString.includes('.bun');
|
37
|
+
|
38
|
+
/* -------------------------------------------------------------------------- */
|
39
|
+
/* VERIFY BUN IS IN PATH */
|
40
|
+
/* -------------------------------------------------------------------------- */
|
41
|
+
if (needsBunInPath) {
|
42
|
+
/**
|
43
|
+
* If BUN_INSTALL is not in the path, we need to add it.
|
44
|
+
* https://bun.sh/docs/installation#checking-installation:~:text=shell%27s%20configuration%20file.
|
45
|
+
*/
|
46
|
+
console.write(
|
47
|
+
'BUN is not installed globally or is not available in your $PATH. Adding to your $PATH...',
|
48
|
+
);
|
49
|
+
const whichShell = await $`echo $SHELL`.text();
|
50
|
+
const homeDirectory = os.homedir();
|
51
|
+
const shellRcFile = whichShell.includes('zsh') ? '.zshrc' : '.bashrc';
|
52
|
+
fs.appendFileSync(
|
53
|
+
`${homeDirectory}/${shellRcFile}`,
|
54
|
+
'\n# bun\nexport BUN_INSTALL="$HOME/.bun"\nexport PATH="$BUN_INSTALL/bin:$PATH"',
|
55
|
+
);
|
56
|
+
await $`source $HOME/${shellRcFile}`;
|
57
|
+
}
|
32
58
|
|
33
59
|
/* -------------------------------------------------------------------------- */
|
34
60
|
/* XCODE SETUP */
|
35
61
|
/* -------------------------------------------------------------------------- */
|
36
62
|
if (isIOS) {
|
37
63
|
const xcodePath = await $`xcode-select -p`.text();
|
38
|
-
const needsXcode = !xcodePath.startsWith('/Applications');
|
39
|
-
const needsXcrun = await needsBinary('xcrun');
|
40
64
|
|
41
|
-
if (
|
42
|
-
|
43
|
-
|
44
|
-
)
|
65
|
+
if (xcodePath) {
|
66
|
+
const isInvalidXcodePath = !xcodePath.startsWith('/Applications');
|
67
|
+
|
68
|
+
if (isInvalidXcodePath) {
|
69
|
+
console.write(`
|
70
|
+
/* -------------------------------------------------------------------------- */
|
71
|
+
/* XCODDE PATH IS INVALID */
|
72
|
+
/* -------------------------------------------------------------------------- */
|
73
|
+
|
74
|
+
Run the following command to set the correct path to XCode:
|
75
|
+
|
76
|
+
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
|
77
|
+
`);
|
78
|
+
}
|
79
|
+
} else {
|
80
|
+
console.write(`
|
81
|
+
/* -------------------------------------------------------------------------- */
|
82
|
+
/* XCODE NOT INSTALLED */
|
83
|
+
/* -------------------------------------------------------------------------- */
|
84
|
+
|
85
|
+
You must have XCode installed before continuing...
|
86
|
+
|
87
|
+
Visit https://apps.apple.com/us/app/xcode/id497799835?mt=12 to download.
|
88
|
+
`);
|
45
89
|
throw new Error('XCode not installed');
|
46
90
|
}
|
47
91
|
|
@@ -49,14 +93,14 @@ export async function setup({
|
|
49
93
|
* Installing the XCode command line tools & simulators normally
|
50
94
|
* requires opening up XCode to install.
|
51
95
|
* This conditional is to avoid having to do that.
|
96
|
+
*
|
97
|
+
* If xcode command line tools and simulators have already been installed, that's
|
98
|
+
* fine. This command is really fast and will continue running if already available.
|
99
|
+
*
|
100
|
+
* https://developer.apple.com/documentation/xcode/installing-additional-simulator-runtimes#Install-and-manage-Simulator-runtimes-from-the-command-line
|
52
101
|
*/
|
53
|
-
|
54
|
-
|
55
|
-
* https://developer.apple.com/documentation/xcode/installing-additional-simulator-runtimes#Install-and-manage-Simulator-runtimes-from-the-command-line
|
56
|
-
*/
|
57
|
-
await $`xcodebuild -runFirstLaunch`;
|
58
|
-
await $`xcodebuild -downloadPlatform iOS`;
|
59
|
-
}
|
102
|
+
await $`xcodebuild -runFirstLaunch`;
|
103
|
+
await $`xcodebuild -downloadPlatform iOS`;
|
60
104
|
}
|
61
105
|
|
62
106
|
/* -------------------------------------------------------------------------- */
|
@@ -215,7 +259,7 @@ export async function setup({
|
|
215
259
|
const output = {
|
216
260
|
name: outputName,
|
217
261
|
dir: outputDir,
|
218
|
-
prebuildsDir
|
262
|
+
prebuildsDir,
|
219
263
|
fileBase: outputFileBase,
|
220
264
|
artifact: isIOS ? `${outputFileBase}.tar.gz` : `${outputFileBase}.zip`,
|
221
265
|
app: isIOS ? `${outputFileBase}.app` : 'todo fix android',
|
package/cli/commands/expo/dev.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import { Props } from 'bluebun';
|
2
2
|
import { $, sleep } from 'bun';
|
3
|
-
|
3
|
+
|
4
|
+
import { type MobileProps, setup } from './_setup';
|
4
5
|
|
5
6
|
interface MobileStartProps extends Props {
|
6
7
|
options: MobileProps['options'] & {
|
@@ -56,15 +57,22 @@ export default {
|
|
56
57
|
const iphone15Udid = iphone15ProMax?.udid;
|
57
58
|
await $`open -a Simulator --args -CurrentDeviceUDID ${iphone15Udid}`;
|
58
59
|
}
|
60
|
+
const appContainerPath =
|
61
|
+
await $`xcrun simctl get_app_container booted ${scheme} data`.text();
|
62
|
+
|
63
|
+
if (!appContainerPath) {
|
64
|
+
console.write('App not installed on booted device. Installing...');
|
65
|
+
await $`eas build:run --platform ${platform} --path ${output.launchFile}`;
|
66
|
+
}
|
67
|
+
/**
|
68
|
+
* In dev mode we use a debug build, which requires a metro server to serve
|
69
|
+
* the Javascript bundle.
|
70
|
+
*
|
71
|
+
* To avoid the, "Could not find metro server" error screen on launch,
|
72
|
+
* we delay the launch of the app until after the metro server has started.
|
73
|
+
*/
|
59
74
|
}
|
60
75
|
|
61
|
-
/**
|
62
|
-
* In dev mode we use a debug build, which requires a metro server to serve
|
63
|
-
* the Javascript bundle.
|
64
|
-
*
|
65
|
-
* To avoid the, "Could not find metro server" error screen on launch,
|
66
|
-
* we delay the launch of the app until after the metro server has started.
|
67
|
-
*/
|
68
76
|
sleep(3000).then(async () => {
|
69
77
|
/**
|
70
78
|
* Launch the app on the booted device
|
@@ -76,6 +84,7 @@ export default {
|
|
76
84
|
console.write('Starting Metro server...');
|
77
85
|
await $`expo start --${platform} --dev-client --localhost --scheme ${scheme} ${extrArgsString}`;
|
78
86
|
} catch (err) {
|
87
|
+
console.error(err);
|
79
88
|
throw err;
|
80
89
|
}
|
81
90
|
},
|
@@ -1,19 +1,19 @@
|
|
1
|
-
import { type Props } from 'bluebun';
|
2
1
|
import { getCommandHelp } from '../../utils/getCommandHelp';
|
2
|
+
import { type MobileProps } from './_setup';
|
3
3
|
|
4
4
|
export default {
|
5
5
|
name: 'expo',
|
6
6
|
description: '',
|
7
|
-
run: async (props:
|
7
|
+
run: async (props: MobileProps) => {
|
8
8
|
switch (props?.first) {
|
9
9
|
case 'build':
|
10
|
-
return
|
10
|
+
return (await import('./build')).default.run(props);
|
11
11
|
case 'dev':
|
12
|
-
return
|
12
|
+
return (await import('./dev')).default.run(props);
|
13
13
|
case 'launch':
|
14
|
-
return
|
14
|
+
return (await import('./launch')).default.run(props);
|
15
15
|
case 'update':
|
16
|
-
return
|
16
|
+
return (await import('./update')).default.run(props);
|
17
17
|
default: {
|
18
18
|
await getCommandHelp(props);
|
19
19
|
break;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { Props, spinStart, spinStop } from 'bluebun';
|
2
|
+
|
3
|
+
import { purge } from '../utils/purgeCSS';
|
4
|
+
|
5
|
+
export default {
|
6
|
+
name: 'purge',
|
7
|
+
description: `Purge unused CSS`,
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
9
|
+
run: async (props: Props) => {
|
10
|
+
spinStart('Purging css...');
|
11
|
+
|
12
|
+
await purge();
|
13
|
+
|
14
|
+
spinStop('✅ Purging css done!');
|
15
|
+
},
|
16
|
+
};
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { Props } from 'bluebun';
|
2
|
-
|
3
|
-
import {
|
2
|
+
|
3
|
+
import { setupConfigWorker } from '../utils/setupConfigWorker';
|
4
|
+
import { SyncOptions } from '../utils/types';
|
4
5
|
|
5
6
|
interface SyncProps extends Props {
|
6
7
|
options: SyncOptions;
|
package/cli/commands/uds.ts
CHANGED
package/cli/env.d.ts
CHANGED
@@ -1,9 +1,31 @@
|
|
1
1
|
// prevents TS errors
|
2
2
|
declare var self: Worker;
|
3
|
+
|
4
|
+
import { $ } from 'bun';
|
5
|
+
|
3
6
|
import { ConfigWorkerThreadMessage } from './types';
|
4
7
|
|
5
8
|
self.onmessage = async ({ data }: ConfigWorkerThreadMessage) => {
|
6
9
|
if (data.type === 'init') {
|
7
|
-
|
10
|
+
try {
|
11
|
+
// Only listen for updates if firebase is available. This will only be available in UDS monorepo atm
|
12
|
+
const firebase = await import('database/firebase');
|
13
|
+
console.write('Fetching from local database package...\n');
|
14
|
+
firebase.onBranchSnapshot(data.resp.id, ({ config, status }) => {
|
15
|
+
postMessage({ type: 'update', resp: { config, status } });
|
16
|
+
});
|
17
|
+
} catch (err) {
|
18
|
+
try {
|
19
|
+
const res =
|
20
|
+
await $`curl https://syncconfig-j57v6zmjrq-uc.a.run.app?id=${data.resp.id}`.json();
|
21
|
+
if (res?.config) {
|
22
|
+
postMessage({ type: 'update', resp: { config: res.config, status: 'error' } });
|
23
|
+
} else {
|
24
|
+
throw Error;
|
25
|
+
}
|
26
|
+
} catch (err) {
|
27
|
+
throw new Error('Error fetching config');
|
28
|
+
}
|
29
|
+
}
|
8
30
|
}
|
9
31
|
};
|
@@ -1,13 +1,12 @@
|
|
1
1
|
import {
|
2
|
-
CommandTree,
|
3
|
-
InitialProps,
|
4
|
-
Props,
|
5
2
|
bold,
|
6
3
|
calcWidestCommandName,
|
4
|
+
CommandTree,
|
7
5
|
commandTree,
|
8
6
|
cyan,
|
9
7
|
gray,
|
10
8
|
print,
|
9
|
+
Props,
|
11
10
|
white,
|
12
11
|
} from 'bluebun';
|
13
12
|
|
@@ -35,7 +34,7 @@ async function formatHelp(initialProps: Props) {
|
|
35
34
|
function generateHelp(cmdTree: CommandTree, prefix: string): string[] {
|
36
35
|
return Object.keys(cmdTree).flatMap((key) => {
|
37
36
|
const command = cmdTree[key];
|
38
|
-
|
37
|
+
const lines: string[] = [];
|
39
38
|
|
40
39
|
const fullName = `${prefix} ${command.name === name ? '' : command.name}`.trim();
|
41
40
|
lines.push(`${cyan(fullName).padEnd(widest)} ${gray(command.description)}`);
|
@@ -0,0 +1,138 @@
|
|
1
|
+
import path from 'node:path';
|
2
|
+
|
3
|
+
import {
|
4
|
+
componentsDependencies,
|
5
|
+
componentToVariants,
|
6
|
+
variantsList,
|
7
|
+
variantToTailwindClass,
|
8
|
+
} from '@yahoo/uds/tailwindPurge';
|
9
|
+
import { spinStart } from 'bluebun';
|
10
|
+
import FastGlob from 'fast-glob';
|
11
|
+
import { Project } from 'ts-morph';
|
12
|
+
|
13
|
+
type SafeList = string;
|
14
|
+
type ImportsList = string[];
|
15
|
+
type Files = string[];
|
16
|
+
|
17
|
+
// TODO: use CLI args to power the output file path
|
18
|
+
const OUTPUT_FILE_PATH = Bun.file(`${Bun.env.PWD}/dist/safelist.js`);
|
19
|
+
|
20
|
+
const getFiles = async (): Promise<Files> => {
|
21
|
+
const workspaceDir = Bun.env.PWD;
|
22
|
+
const srcDir = path.join(workspaceDir, '/src/');
|
23
|
+
const files = await FastGlob(`${srcDir}/**/*.{jsx,tsx}`);
|
24
|
+
|
25
|
+
return files;
|
26
|
+
};
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Given a file it returns the list of imports from @yahoo/uds
|
30
|
+
*/
|
31
|
+
const parseFiles = (project: Project, files: Files): ImportsList => {
|
32
|
+
const importsSet = new Set();
|
33
|
+
|
34
|
+
const importsPerFile: string[] = files
|
35
|
+
.map((file: string) => {
|
36
|
+
const sourceFile = project.getSourceFile(file);
|
37
|
+
|
38
|
+
const udsImports =
|
39
|
+
sourceFile
|
40
|
+
?.getImportDeclarations()
|
41
|
+
.filter((declaration) => {
|
42
|
+
return declaration.getModuleSpecifier().getText().includes('@yahoo/uds');
|
43
|
+
})
|
44
|
+
.map((declaration) => {
|
45
|
+
return declaration.getNamedImports().map((namedImport) => namedImport.getName());
|
46
|
+
})
|
47
|
+
.flat() ?? [];
|
48
|
+
|
49
|
+
return udsImports;
|
50
|
+
})
|
51
|
+
.flat();
|
52
|
+
|
53
|
+
importsPerFile.forEach((item: string) => {
|
54
|
+
if (!importsSet.has(item)) {
|
55
|
+
importsSet.add(item);
|
56
|
+
}
|
57
|
+
});
|
58
|
+
|
59
|
+
return Array.from(importsSet) as string[];
|
60
|
+
};
|
61
|
+
|
62
|
+
const getTailwindSafelist = (componentList: string[]): SafeList => {
|
63
|
+
const validVariants = new Set<string>(variantsList);
|
64
|
+
const usedProps = new Set<string>();
|
65
|
+
componentList.forEach((component: string) => {
|
66
|
+
if (isUDSComponent(component)) {
|
67
|
+
// go through the list of props of that particular component
|
68
|
+
// and get the related tailwind classes
|
69
|
+
componentToVariants[component].forEach((prop: string) => {
|
70
|
+
if (validVariants.has(prop) && !usedProps.has(prop)) {
|
71
|
+
usedProps.add(prop);
|
72
|
+
}
|
73
|
+
});
|
74
|
+
}
|
75
|
+
});
|
76
|
+
|
77
|
+
let safeList = '';
|
78
|
+
for (const prop of usedProps) {
|
79
|
+
safeList += `${variantToTailwindClass[prop]} `;
|
80
|
+
}
|
81
|
+
return safeList;
|
82
|
+
};
|
83
|
+
|
84
|
+
const isUDSComponent = (component: string): boolean => {
|
85
|
+
return !!componentToVariants[component];
|
86
|
+
};
|
87
|
+
|
88
|
+
const saveToFile = async (safeList: SafeList) => {
|
89
|
+
const fileContent = `
|
90
|
+
//! This file is generated by purgeCSS.ts from @yahoo/uds
|
91
|
+
//! Do not edit directly
|
92
|
+
//! If there is issue with this file please report to #ask-uds
|
93
|
+
const safeList = "${safeList}";
|
94
|
+
`;
|
95
|
+
|
96
|
+
await Bun.write(OUTPUT_FILE_PATH, fileContent);
|
97
|
+
};
|
98
|
+
|
99
|
+
const getComponentsToConvertToTW = (udsImport: ImportsList): string[] => {
|
100
|
+
// filter out just the components
|
101
|
+
const components = udsImport.filter((importedItem) => !!componentToVariants[importedItem]);
|
102
|
+
const set = new Set();
|
103
|
+
components.forEach((component) => {
|
104
|
+
if (!set.has(component)) {
|
105
|
+
set.add(component);
|
106
|
+
}
|
107
|
+
if (componentsDependencies[component]) {
|
108
|
+
componentsDependencies[component].forEach((dependent: string) => {
|
109
|
+
if (!set.has(dependent)) {
|
110
|
+
set.add(dependent);
|
111
|
+
}
|
112
|
+
});
|
113
|
+
}
|
114
|
+
});
|
115
|
+
return Array.from(set) as string[];
|
116
|
+
};
|
117
|
+
|
118
|
+
async function purge() {
|
119
|
+
const workspaceDir = Bun.env.PWD;
|
120
|
+
const srcDir = path.join(workspaceDir, '/tsconfig.json');
|
121
|
+
const project = new Project({
|
122
|
+
tsConfigFilePath: srcDir,
|
123
|
+
});
|
124
|
+
|
125
|
+
spinStart('Getting used UDS components...');
|
126
|
+
/// 1. Get all files from the current dir
|
127
|
+
const files = await getFiles();
|
128
|
+
// 2. For each file get the imports;
|
129
|
+
const udsImports = parseFiles(project, files);
|
130
|
+
// 3. Now that we have the importer components
|
131
|
+
const udsComponents = getComponentsToConvertToTW(udsImports);
|
132
|
+
// 4. Generate the CSS we need
|
133
|
+
const safeList = getTailwindSafelist(udsComponents);
|
134
|
+
// 5. Write the allowlist to a file
|
135
|
+
await saveToFile(safeList);
|
136
|
+
}
|
137
|
+
|
138
|
+
export { purge };
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import path from 'node:path';
|
2
|
-
|
2
|
+
|
3
3
|
import { sortKeys } from './sortKeys';
|
4
|
+
import { ConfigWorkerMainThreadMessage, SyncOptions } from './types';
|
4
5
|
|
5
6
|
const workerPath = path.resolve(import.meta.dir, './configWorker');
|
6
7
|
const workerURL = new URL(Bun.pathToFileURL(workerPath)).href;
|
@@ -9,45 +10,41 @@ interface ConfigWorkerOptions extends SyncOptions {
|
|
9
10
|
onUpdate?: (params: { worker: Worker }) => void;
|
10
11
|
}
|
11
12
|
|
12
|
-
export async function setupConfigWorker({
|
13
|
+
export async function setupConfigWorker({
|
14
|
+
id = Bun.env.UDS_ID,
|
15
|
+
outFile = Bun.env.UDS_OUT_FILE,
|
16
|
+
onUpdate,
|
17
|
+
}: ConfigWorkerOptions = {}) {
|
13
18
|
const workspaceDir = Bun.env.PWD;
|
14
19
|
let configID = id;
|
15
|
-
let configOutFile = outFile;
|
20
|
+
let configOutFile = outFile ?? './uds.config.ts';
|
16
21
|
|
22
|
+
// If we didn't get the config ID from the command line or env vars, check for a uds.json file
|
17
23
|
if (!configID) {
|
18
24
|
const udsConfigFile = Bun.file(`${workspaceDir}/uds.json`);
|
19
25
|
const udsConfigFileExists = await udsConfigFile.exists();
|
20
26
|
if (udsConfigFileExists) {
|
21
|
-
const configJsonFile = await udsConfigFile.json
|
22
|
-
id: string;
|
23
|
-
outFile: string;
|
24
|
-
}>();
|
27
|
+
const configJsonFile = (await udsConfigFile.json()) as { id: string; outFile: string };
|
25
28
|
|
26
29
|
configID = configJsonFile.id;
|
27
30
|
configOutFile = configJsonFile.outFile;
|
28
31
|
}
|
29
32
|
}
|
30
33
|
|
34
|
+
// have _nothing_, warn the eng to do something
|
31
35
|
if (!configID) {
|
32
36
|
console.error(
|
33
|
-
'\nMissing config ID. Please pass in --id or create a uds.json file with { "id": "your-config-id" } defined.\n',
|
34
|
-
);
|
35
|
-
process.exit(1);
|
36
|
-
}
|
37
|
-
|
38
|
-
if (!configOutFile) {
|
39
|
-
console.error(
|
40
|
-
'\nMissing outFile details. Please pass in --outFile ./some-path.ts or create a uds.json file with { "outFile": "./some-path.ts" } defined.\n',
|
37
|
+
'\nMissing config ID. Please pass in --id, set UDS_ID in your .env, or create a uds.json file with { "id": "your-config-id" } defined.\n',
|
41
38
|
);
|
42
39
|
process.exit(1);
|
43
40
|
}
|
44
41
|
|
45
|
-
const outFilePath = `${workspaceDir}/${
|
42
|
+
const outFilePath = `${workspaceDir}/${configOutFile}`;
|
46
43
|
|
47
44
|
const worker = new Worker(workerURL);
|
48
45
|
|
49
46
|
worker.addEventListener('open', () => {
|
50
|
-
worker.postMessage({ type: 'init', resp: { id } });
|
47
|
+
worker.postMessage({ type: 'init', resp: { id: configID } });
|
51
48
|
});
|
52
49
|
|
53
50
|
worker.onmessage = async ({ data }: ConfigWorkerMainThreadMessage) => {
|
@@ -62,7 +59,7 @@ import { type UniversalTokensConfig } from '@yahoo/uds';
|
|
62
59
|
export const config: UniversalTokensConfig = ${JSON.stringify(sortedConfig, null, 2)};
|
63
60
|
`.trimStart();
|
64
61
|
|
65
|
-
console.log(`✅ Synced UDS config ${
|
62
|
+
console.log(`✅ Synced UDS config ${configID} to ${outFilePath}`);
|
66
63
|
await Bun.write(outFilePath, configContent);
|
67
64
|
onUpdate?.({ worker });
|
68
65
|
}
|
@@ -1 +1 @@
|
|
1
|
-
var e=["Helvetica Neue","Helvetica","Arial","sans-serif"],
|
1
|
+
var e=["Helvetica Neue","Helvetica","Arial","sans-serif"],i=["Georgia","Times","Times New Roman","serif"],g={icons:{fallbacks:e,name:"yahoo-icons"},sans:{fallbacks:e,name:"yahoo-sans"},"sans-beta":{fallbacks:e,name:"yahoo-sans-beta"},"sans-condensed":{fallbacks:e,name:"yahoo-sans-condensed"},"serif-text":{fallbacks:i,name:"yahoo-serif-text"},"serif-display":{fallbacks:i,name:"yahoo-serif-display"}},b={display1:"sans",title1:"sans",title2:"sans",title3:"sans",title4:"sans",headline1:"sans",body1:"sans",label1:"sans",label2:"sans",caption1:"sans",caption2:"sans",legal1:"sans"},f={thin:"100",extralight:"200",light:"300",regular:"400",medium:"500",semibold:"600",bold:"700",extrabold:"800",black:"900"},p={display1:"black",title1:"bold",title2:"bold",title3:"bold",title4:"bold",headline1:"semibold",body1:"regular",label1:"semibold",label2:"regular",caption1:"semibold",caption2:"regular",legal1:"semibold"},d={display1:"uppercase",title1:"none",title2:"none",title3:"none",title4:"none",headline1:"none",body1:"none",label1:"none",label2:"none",caption1:"none",caption2:"none",legal1:"none"},l={fontSize:{display1:46,title1:29,title2:25,title3:21,title4:17,headline1:13,body1:13,label1:12,label2:12,caption1:11,caption2:11,legal1:10},lineHeight:{display1:44,title1:36,title2:32,title3:28,title4:24,headline1:16,body1:16,label1:16,label2:16,caption1:16,caption2:16,legal1:12}},a={fontSize:{display1:46,title1:30,title2:26,title3:22,title4:18,headline1:14,body1:14,label1:13,label2:13,caption1:12,caption2:12,legal1:11},lineHeight:{...l.lineHeight,title1:40,headline1:20,body1:20,legal1:16}},t={fontSize:{display1:47,title1:31,title2:27,title3:23,title4:19,headline1:15,body1:15,label1:13,label2:13,caption1:12,caption2:12,legal1:11},lineHeight:{...a.lineHeight,title2:36,title3:32}},n={fontSize:{...t.fontSize,display1:48,title1:32,title2:28,title3:24,title4:20,headline1:16,body1:16,label1:14,label2:14},lineHeight:{...t.lineHeight,title2:36,title3:32,headline1:20,body1:20,label1:20,label2:20}},o={fontSize:{display1:50,title1:34,title2:30,title3:26,title4:22,headline1:18,body1:16,label1:16,label2:16,caption1:14,caption2:14,legal1:13},lineHeight:{...n.lineHeight,title1:44,headline1:24,body1:24,caption1:20,caption2:20}},s={fontSize:{display1:52,title1:36,title2:32,title3:28,title4:26,headline1:20,body1:20,label1:18,label2:18,caption1:16,caption2:16,legal1:15},lineHeight:{...o.lineHeight,title2:40,title3:36,headline1:28,body1:28,label1:24,label2:24,legal1:20}},c={fontSize:{display1:54,title1:38,title2:34,title3:30,title4:28,headline1:22,body1:22,label1:20,label2:20,caption1:18,caption2:18,legal1:17},lineHeight:{...s.lineHeight,title1:48,title2:44,title4:32,label1:28,label2:28,caption1:24,caption2:24}};export{g as a,b,f as c,p as d,d as e,l as f,a as g,t as h,n as i,o as j,s as k,c as l};
|
@@ -1 +1 @@
|
|
1
|
-
import{a as v,b as R,c as m,d as T,e as F,f as $,g as C,h as _,i as E,j as h,k as S}from"./chunk-3I3D5S54.js";import{
|
1
|
+
import{a as y}from"./chunk-WYDHNV42.js";import{a as v,b as R,c as m,d as T,e as F,f as $,g as C,h as _,i as E,j as h,k as S}from"./chunk-3I3D5S54.js";import{a as c}from"./chunk-74YHFBTD.js";import{c as d}from"./chunk-AHFH5E5L.js";function I(o){let{palette:e,spectrum:a}=o,n={},r={spectrum:{},palette:{}};for(let[t,i]of c(a))for(let[s,f]of c(i)){let l=`${t}-${s}`,p=`--${R}-${l}`;r.spectrum[t]||(r.spectrum[t]={}),r.spectrum[t][s]=`rgb(var(${p}))`,n[p]=f}return c(e).forEach(([t,i])=>{for(let[s,{hue:f,step:l,opacity:p}]of Object.entries(i)){t in r.palette||(r.palette[t]={});let g=`--${v}-${t}-color-${s}`;n[g]=`var(--${R}-${f}-${l})`,r.palette[t][s]=p?`rgb(var(${g}) / ${p})`:`rgb(var(${g}))`}}),{_vars:n,_raw:o,tailwindConfig:r}}function k(o){let e={},a={};for(let[n,r="regular"]of c(o)){let t=`--${h}-${n}`,i=d[r];e[t]=i,a[n]=`var(${t})`}return{_vars:e,_raw:o,tailwindConfig:{...d,...a}}}function P(o,e,a){let n={},r={};for(let[t,i]of c(e)){let s=`--${o}-${t}`,f=a?a(i):i;n[s]=f,r[t]=`var(${s})`}return{_vars:n,_raw:e,tailwindConfig:r}}function u(o,e){let a={},n={};for(let[r,t]of c(e)){let i=`--${o}-${r}`,s=`${t}px`;a[i]=s,n[r]=`var(${i})`}return{_vars:a,_raw:e,tailwindConfig:n}}function x(o){let e={};for(let[a,n]of c(o)){let r=n.map(({color:t,offsetX:i,offsetY:s,blurRadius:f,spreadRadius:l})=>`${i}px ${s}px ${f}px ${l}px ${t}`).join(", ");e[a]=r}return e}function N(o){return y(o,(e,a)=>{let{fallbacks:n=[]}=e??{};return[`var(--${m}-${a})`,...n]})}function X(o){return`${o}px`}function w(o){return y(o,X)}var H=w;function U(o){let{colorMode:e,scaleMode:a,elevation:n,fontFamily:r,borderWidth:t}=o;return{...o,colorMode:{light:I(e.light),dark:I(e.dark)},scaleMode:y(a,({shapes:i,spacing:s,fontSize:f,lineHeight:l,fontFamily:p,fontWeight:g,textTransform:b,avatarSizes:V,iconSizes:W})=>({fontFamily:P(m,p,M=>`var(--${m}-${M})`),fontSize:u(_,f),fontWeight:k(g),lineHeight:u(E,l),textTransform:P(S,b),shapes:u($,i),spacing:u(C,s),avatarSizes:u(F,V),iconSizes:u(T,W)})),borderWidth:H(t),elevation:x(n),fontFamily:N(r)}}export{U as a};
|