@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.
Files changed (63) hide show
  1. package/cli/README.md +57 -5
  2. package/cli/commands/expo/_setup.ts +59 -15
  3. package/cli/commands/expo/build.ts +2 -1
  4. package/cli/commands/expo/dev.ts +17 -8
  5. package/cli/commands/expo/expo.ts +6 -6
  6. package/cli/commands/expo/launch.ts +1 -0
  7. package/cli/commands/expo/update.ts +1 -0
  8. package/cli/commands/purge.ts +16 -0
  9. package/cli/commands/{config/sync.ts → sync.ts} +3 -2
  10. package/cli/commands/uds.ts +1 -0
  11. package/cli/env.d.ts +3 -0
  12. package/cli/utils/configWorker.ts +23 -1
  13. package/cli/utils/getCommandHelp.ts +3 -4
  14. package/cli/utils/purgeCSS.ts +138 -0
  15. package/cli/utils/setupConfigWorker.ts +15 -18
  16. package/dist/{chunk-P7GR6E3K.js → chunk-AHFH5E5L.js} +1 -1
  17. package/dist/{chunk-MBOOJIH7.js → chunk-FLBMVDKG.js} +1 -1
  18. package/dist/{chunk-AWTLI4D3.js → chunk-U3UPAQ7V.js} +1 -1
  19. package/dist/fixtures/index.cjs +1 -1
  20. package/dist/fixtures/index.d.cts +1 -3
  21. package/dist/fixtures/index.d.ts +1 -3
  22. package/dist/fixtures/index.js +1 -1
  23. package/dist/index.cjs +1 -1
  24. package/dist/index.d.cts +103 -32
  25. package/dist/index.d.ts +103 -32
  26. package/dist/index.js +1 -1
  27. package/dist/{index.native-9kYJrUPa.d.ts → index.native-fciGC1AQ.d.cts} +2 -2
  28. package/dist/{index.native-3ww4C4UV.d.cts → index.native-hIYZ_ma-.d.ts} +2 -2
  29. package/dist/index.native.cjs +1 -1
  30. package/dist/index.native.d.cts +10 -24
  31. package/dist/index.native.d.ts +10 -24
  32. package/dist/index.native.js +1 -1
  33. package/dist/tailwindPlugin.cjs +1 -1
  34. package/dist/tailwindPlugin.d.cts +1 -1
  35. package/dist/tailwindPlugin.d.ts +1 -1
  36. package/dist/tailwindPlugin.js +1 -1
  37. package/dist/tailwindPurge.cjs +4 -0
  38. package/dist/tailwindPurge.d.cts +16 -0
  39. package/dist/tailwindPurge.d.ts +16 -0
  40. package/dist/tailwindPurge.js +4 -0
  41. package/dist/tokens/index.cjs +1 -1
  42. package/dist/tokens/index.d.cts +3 -3
  43. package/dist/tokens/index.d.ts +3 -3
  44. package/dist/tokens/index.js +1 -1
  45. package/dist/tokens/index.native.cjs +1 -1
  46. package/dist/tokens/index.native.d.cts +2 -2
  47. package/dist/tokens/index.native.d.ts +2 -2
  48. package/dist/tokens/index.native.js +1 -1
  49. package/dist/tokens/parseTokens.cjs +1 -1
  50. package/dist/tokens/parseTokens.d.cts +12 -12
  51. package/dist/tokens/parseTokens.d.ts +12 -12
  52. package/dist/tokens/parseTokens.js +1 -1
  53. package/dist/tokens/parseTokens.native.d.cts +2 -2
  54. package/dist/tokens/parseTokens.native.d.ts +2 -2
  55. package/dist/{types-J4DLS6Xj.d.cts → types-3GXulqnG.d.cts} +1 -1
  56. package/dist/{types-J4DLS6Xj.d.ts → types-3GXulqnG.d.ts} +1 -1
  57. package/dist/{types-hirL9Qk5.d.cts → types-_E6o7OhU.d.cts} +47 -54
  58. package/dist/{types-hirL9Qk5.d.ts → types-_E6o7OhU.d.ts} +47 -54
  59. package/package.json +20 -4
  60. package/cli/commands/config/config.ts +0 -10
  61. package/cli/commands/nextjs/dev.ts +0 -17
  62. package/cli/commands/nextjs/nextjs.ts +0 -10
  63. package/cli/eslint.config.mjs +0 -8
package/cli/README.md CHANGED
@@ -1,16 +1,68 @@
1
- # UDS ClI
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
- # Standalone executable
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
- ## Command structure
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, print } from 'bluebun';
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 (needsXcode) {
42
- console.write(
43
- 'You must have XCode installed before continuing... Visit https://apps.apple.com/us/app/xcode/id497799835?mt=12 to download.',
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
- if (needsXcrun) {
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: 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',
@@ -1,5 +1,6 @@
1
1
  import { $, semver } from 'bun';
2
- import { setup, needsBinary, needsBrewFormula, type MobileProps } from './_setup';
2
+
3
+ import { type MobileProps, needsBinary, needsBrewFormula, setup } from './_setup';
3
4
 
4
5
  export default {
5
6
  name: 'build',
@@ -1,6 +1,7 @@
1
1
  import { Props } from 'bluebun';
2
2
  import { $, sleep } from 'bun';
3
- import { setup, type MobileProps } from './_setup';
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: Props) => {
7
+ run: async (props: MobileProps) => {
8
8
  switch (props?.first) {
9
9
  case 'build':
10
- return require('./build').default.run(props);
10
+ return (await import('./build')).default.run(props);
11
11
  case 'dev':
12
- return require('./dev').default.run(props);
12
+ return (await import('./dev')).default.run(props);
13
13
  case 'launch':
14
- return require('./launch').default.run(props);
14
+ return (await import('./launch')).default.run(props);
15
15
  case 'update':
16
- return require('./update').default.run(props);
16
+ return (await import('./update')).default.run(props);
17
17
  default: {
18
18
  await getCommandHelp(props);
19
19
  break;
@@ -1,4 +1,5 @@
1
1
  import { $ } from 'bun';
2
+
2
3
  import type { MobileProps } from './_setup';
3
4
  import { setup } from './_setup';
4
5
 
@@ -1,4 +1,5 @@
1
1
  import { $ } from 'bun';
2
+
2
3
  import type { MobileProps } from './_setup';
3
4
  import { setup } from './_setup';
4
5
 
@@ -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
- import { setupConfigWorker } from '../../utils/setupConfigWorker';
3
- import { SyncOptions } from '../../utils/types';
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;
@@ -1,4 +1,5 @@
1
1
  import { type Props } from 'bluebun';
2
+
2
3
  import { getCommandHelp } from '../utils/getCommandHelp';
3
4
 
4
5
  export default {
package/cli/env.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ // See https://github.com/oven-sh/bun/issues/8736
2
+ /// <reference types="bun-types/overrides.d.ts" />
3
+
1
4
  declare module 'bun' {
2
5
  interface Env {
3
6
  PWD: string;
@@ -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
- console.log('setup websocket endpoint to watch for config updates');
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
- let lines: string[] = [];
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
- import { ConfigWorkerMainThreadMessage, SyncOptions } from './types';
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({ id, outFile, onUpdate }: ConfigWorkerOptions = {}) {
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}/${outFile}`;
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 ${id}`);
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"],l=["Georgia","Times","Times New Roman","serif"],b={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:l,name:"yahoo-serif-text"},"serif-display":{fallbacks:l,name:"yahoo-serif-display"}},d={display1:"sans",title1:"sans",title2:"sans",title3:"sans",title4:"sans",headline1:"sans",body1:"sans",label1:"sans",label2:"sans",caption1:"sans",caption2:"sans",legal1:"sans"},p={thin:"100",extralight:"200",light:"300",regular:"400",medium:"500",semibold:"600",bold:"700",extrabold:"800",black:"900"},c={display1:"black",title1:"bold",title2:"bold",title3:"bold",title4:"bold",headline1:"semibold",body1:"regular",label1:"semibold",label2:"regular",caption1:"semibold",caption2:"regular",legal1:"semibold"},g={display1:"uppercase",title1:"none",title2:"none",title3:"none",title4:"none",headline1:"none",body1:"none",label1:"none",label2:"none",caption1:"none",caption2:"none",legal1:"none"},i={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:{...i.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}},r={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{b as a,d as b,p as c,c as d,g as e,i as f,a as g,t as h,n as i,o as j,s as k,r as l};
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{c as d}from"./chunk-P7GR6E3K.js";import{a as y}from"./chunk-WYDHNV42.js";import{a as c}from"./chunk-74YHFBTD.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};
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};