@yahoo/uds 0.1.11 → 0.1.13
Sign up to get free protection for your applications and to get access to all the features.
- package/cli/README.md +135 -0
- package/cli/commands/config/config.ts +10 -0
- package/cli/commands/config/sync.ts +22 -0
- package/cli/commands/expo/_setup.ts +260 -0
- package/cli/commands/expo/build.ts +15 -0
- package/cli/commands/expo/dev.ts +79 -0
- package/cli/commands/expo/expo.ts +23 -0
- package/cli/commands/expo/launch.ts +15 -0
- package/cli/commands/expo/update.ts +16 -0
- package/cli/commands/nextjs/dev.ts +17 -0
- package/cli/commands/nextjs/nextjs.ts +10 -0
- package/cli/commands/uds.ts +10 -0
- package/cli/commands/version.ts +11 -0
- package/cli/env.d.ts +15 -0
- package/cli/eslint.config.mjs +8 -0
- package/cli/tsconfig.json +10 -0
- package/cli/uds-cli +7 -0
- package/cli/utils/configWorker.ts +9 -0
- package/cli/utils/getCommandHelp.ts +65 -0
- package/cli/utils/setupConfigWorker.ts +81 -0
- package/cli/utils/sortKeys.ts +27 -0
- package/cli/utils/types.ts +13 -0
- package/dist/chunk-3I3D5S54.js +1 -0
- package/dist/chunk-74YHFBTD.js +1 -0
- package/dist/chunk-AWTLI4D3.js +1 -0
- package/dist/chunk-D4K3CXV6.js +0 -0
- package/dist/chunk-M346JMQS.js +0 -0
- package/dist/chunk-MBOOJIH7.js +1 -0
- package/dist/chunk-MFA2Y7DA.js +1 -0
- package/dist/chunk-P7GR6E3K.js +1 -0
- package/dist/chunk-PQBOZFJV.js +1 -0
- package/dist/chunk-WYDHNV42.js +1 -0
- package/dist/fixtures/index.cjs +1 -0
- package/dist/fixtures/index.d.cts +141 -0
- package/dist/fixtures/index.d.ts +141 -0
- package/dist/fixtures/index.js +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +62 -93
- package/dist/index.d.ts +62 -93
- package/dist/index.js +1 -1
- package/dist/index.native-3ww4C4UV.d.cts +15 -0
- package/dist/index.native-9kYJrUPa.d.ts +15 -0
- package/dist/index.native.cjs +1 -0
- package/dist/index.native.d.cts +1493 -0
- package/dist/index.native.d.ts +1493 -0
- package/dist/index.native.js +1 -0
- package/dist/tailwindPlugin.cjs +1 -1
- package/dist/tailwindPlugin.d.cts +2 -1
- package/dist/tailwindPlugin.d.ts +2 -1
- package/dist/tailwindPlugin.js +1 -1
- package/dist/tokens/index.cjs +1 -0
- package/dist/tokens/index.d.cts +39 -0
- package/dist/tokens/index.d.ts +39 -0
- package/dist/tokens/index.js +1 -0
- package/dist/tokens/index.native.cjs +1 -0
- package/dist/tokens/index.native.d.cts +3 -0
- package/dist/tokens/index.native.d.ts +3 -0
- package/dist/tokens/index.native.js +1 -0
- package/dist/tokens/parseTokens.cjs +1 -0
- package/dist/tokens/parseTokens.d.cts +85 -0
- package/dist/tokens/parseTokens.d.ts +85 -0
- package/dist/tokens/parseTokens.js +1 -0
- package/dist/tokens/parseTokens.native.cjs +1 -0
- package/dist/tokens/parseTokens.native.d.cts +416 -0
- package/dist/tokens/parseTokens.native.d.ts +416 -0
- package/dist/tokens/parseTokens.native.js +1 -0
- package/dist/types-J4DLS6Xj.d.cts +38 -0
- package/dist/types-J4DLS6Xj.d.ts +38 -0
- package/dist/types-hirL9Qk5.d.cts +510 -0
- package/dist/types-hirL9Qk5.d.ts +510 -0
- package/fonts/mobile.cjs +29 -0
- package/fonts/mobile.d.ts +3 -0
- package/fonts/yahoo-icons.ttf +0 -0
- package/fonts/yahoo-sans-beta-bold.otf +0 -0
- package/fonts/yahoo-sans-beta-medium.otf +0 -0
- package/fonts/yahoo-sans-beta-regular.otf +0 -0
- package/fonts/yahoo-sans-black.otf +0 -0
- package/fonts/yahoo-sans-bold.otf +0 -0
- package/fonts/yahoo-sans-condensed-black.otf +0 -0
- package/fonts/yahoo-sans-condensed-bold.otf +0 -0
- package/fonts/yahoo-sans-condensed-light.otf +0 -0
- package/fonts/yahoo-sans-condensed-medium.otf +0 -0
- package/fonts/yahoo-sans-condensed-regular.otf +0 -0
- package/fonts/yahoo-sans-extrabold.otf +0 -0
- package/fonts/yahoo-sans-extralight.otf +0 -0
- package/fonts/yahoo-sans-italic.otf +0 -0
- package/fonts/yahoo-sans-light.otf +0 -0
- package/fonts/yahoo-sans-medium.otf +0 -0
- package/fonts/yahoo-sans-regular.otf +0 -0
- package/fonts/yahoo-sans-semibold.otf +0 -0
- package/fonts/yahoo-serif-display-black.otf +0 -0
- package/fonts/yahoo-serif-display-bold.otf +0 -0
- package/fonts/yahoo-serif-display-extrabold.otf +0 -0
- package/fonts/yahoo-serif-display-light.otf +0 -0
- package/fonts/yahoo-serif-display-regular.otf +0 -0
- package/fonts/yahoo-serif-text-bold.otf +0 -0
- package/fonts/yahoo-serif-text-italic.otf +0 -0
- package/fonts/yahoo-serif-text-regular.otf +0 -0
- package/package.json +130 -35
- package/bin/uds +0 -0
package/cli/README.md
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
# UDS ClI
|
2
|
+
|
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
|
+
|
5
|
+
Bluebun relies on Bun APIs and is designed to be extremely fast, with no-dependencies.
|
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.
|
10
|
+
|
11
|
+
# Commands
|
12
|
+
|
13
|
+
## Command structure
|
14
|
+
|
15
|
+
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
|
+
|
17
|
+
For example, a command structure might look like this:
|
18
|
+
|
19
|
+
```
|
20
|
+
cli/
|
21
|
+
commands/
|
22
|
+
pizza.ts # pizza
|
23
|
+
help.ts # pizza help
|
24
|
+
bake/
|
25
|
+
bake.ts # pizza bake
|
26
|
+
cheese.ts # pizza bake cheese
|
27
|
+
pepperoni.ts # pizza bake pepperoni
|
28
|
+
```
|
29
|
+
|
30
|
+
## Command files
|
31
|
+
|
32
|
+
Commands are exported as defaults from each command file. They look like this:
|
33
|
+
|
34
|
+
```typescript
|
35
|
+
import { type Props } from 'bluebun';
|
36
|
+
|
37
|
+
export default {
|
38
|
+
name: 'bake',
|
39
|
+
description: 'Bake a pizza',
|
40
|
+
alias: ['b'],
|
41
|
+
run: async (props: Props) => {
|
42
|
+
// bake it!
|
43
|
+
},
|
44
|
+
};
|
45
|
+
```
|
46
|
+
|
47
|
+
## Command properties
|
48
|
+
|
49
|
+
Commands have the following properties:
|
50
|
+
|
51
|
+
- `name` - the name of the command
|
52
|
+
- `description` - a description of the command for the automatic help system
|
53
|
+
- `alias` - an array of aliases for the command (can also be a single string)
|
54
|
+
- `run` - the function that is run when the command is run, usually `async`
|
55
|
+
|
56
|
+
## Props
|
57
|
+
|
58
|
+
The `run` function is passed a `Props` object. This object contains the command path, the arguments, and the options, as well as a few other useful things.
|
59
|
+
|
60
|
+
Here are the properties available on the `props` object if we were to run `uds bake cheese convection --sliced --temp=400 --time 30`:
|
61
|
+
|
62
|
+
- `name` - the name of the CLI (uds)
|
63
|
+
- `cliPath` - the path to the CLI (./uds-cli)
|
64
|
+
- `argv` - the raw arguments passed to the CLI (e.g. `["/bin/bun", "/bin/uds", "bake", "cheese", "convection", "--sliced", "--temp=400", "--time", "30"]`)
|
65
|
+
- `commandPath` - the path to the command that was run (e.g. `["bake", "cheese"]`)
|
66
|
+
- `arguments` - the positional arguments passed to the command (e.g. `["convection"]`)
|
67
|
+
- `options` - the options passed to the command (e.g. `{ sliced: true, temp: 400, time: 30 }`)
|
68
|
+
- `first` - the first argument passed to the command (e.g. `"convection"`)
|
69
|
+
- `second` - the second argument passed to the command (e.g. `undefined`)
|
70
|
+
- `third` - the third argument passed to the command (e.g. `undefined`)
|
71
|
+
|
72
|
+
Given these props, we might have a command that looks like this:
|
73
|
+
|
74
|
+
```typescript
|
75
|
+
import { type Props, spinStart, spinStop } from 'bluebun';
|
76
|
+
import { createPizza, slice } from './_pizza';
|
77
|
+
import { convectionBake, toasterBake, regularBake } from './_bakePizza';
|
78
|
+
|
79
|
+
export default {
|
80
|
+
name: 'bake',
|
81
|
+
description: 'Bake a pizza',
|
82
|
+
alias: ['b'],
|
83
|
+
run: async (props: Props) => {
|
84
|
+
const { first, second, third, options } = props;
|
85
|
+
|
86
|
+
const pizza = createPizza();
|
87
|
+
|
88
|
+
spinStart('Baking pizza...');
|
89
|
+
if (first === 'convection') {
|
90
|
+
await convectionBake(pizza, options.temp, options.time);
|
91
|
+
} else if (first === 'toaster') {
|
92
|
+
await toasterBake(pizza, options.temp, options.time);
|
93
|
+
} else {
|
94
|
+
await regularBake(pizza, options.temp, options.time);
|
95
|
+
}
|
96
|
+
spinStop('✅ Pizza baked!');
|
97
|
+
|
98
|
+
spinStart('Slicing pizza...');
|
99
|
+
if (options.sliced) {
|
100
|
+
await slice(pizza);
|
101
|
+
}
|
102
|
+
spinStop('✅ Pizza sliced!');
|
103
|
+
},
|
104
|
+
};
|
105
|
+
```
|
106
|
+
|
107
|
+
# Reference
|
108
|
+
|
109
|
+
Bluebun comes with a number of built-in utilities that are useful. They're all exported from `bluebun` directly, so you can import them like this:
|
110
|
+
|
111
|
+
```typescript
|
112
|
+
import { inputKey } from 'bluebun';
|
113
|
+
```
|
114
|
+
|
115
|
+
Each of the following docs has usage examples and a Testing section that gives examples on how to write tests for them.
|
116
|
+
|
117
|
+
## CLI
|
118
|
+
|
119
|
+
- [run](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/run.md) - run the CLI and command
|
120
|
+
- [cli](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/cli.md) - start the CLI without running the command
|
121
|
+
- [commandHelp](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/commandHelp.md) - get a list of all commands and their descriptions
|
122
|
+
|
123
|
+
## User Interaction
|
124
|
+
|
125
|
+
- [ask](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/ask.md) - ask the user a question via a prompt
|
126
|
+
- [cursor](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/cursor.md) - manipulate the cursor
|
127
|
+
- [inputKey](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/inputKey.md) - wait for a single keypress
|
128
|
+
- [inputKeys](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/inputKeys.md) - wait for and handle multiple keypresses
|
129
|
+
|
130
|
+
## Output
|
131
|
+
|
132
|
+
- [print](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/print.md) - print a string to the terminal
|
133
|
+
- [spinner](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/spinner.md) - start and stop a spinner
|
134
|
+
- [progress](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/progress.md) - start, update, and stop a progress bar
|
135
|
+
- [styles and colors](https://github.com/jamonholmgren/bluebun/blob/main/docs/reference/styles.md) - style and colorize text
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { Props } from 'bluebun';
|
2
|
+
import { setupConfigWorker } from '../../utils/setupConfigWorker';
|
3
|
+
import { SyncOptions } from '../../utils/types';
|
4
|
+
|
5
|
+
interface SyncProps extends Props {
|
6
|
+
options: SyncOptions;
|
7
|
+
}
|
8
|
+
|
9
|
+
export default {
|
10
|
+
name: 'sync',
|
11
|
+
description: '🌈 Sync',
|
12
|
+
run: async ({ options }: SyncProps) => {
|
13
|
+
await setupConfigWorker({
|
14
|
+
...options,
|
15
|
+
onUpdate: ({ worker }) => {
|
16
|
+
if (!options.watch) {
|
17
|
+
worker.terminate();
|
18
|
+
}
|
19
|
+
},
|
20
|
+
});
|
21
|
+
},
|
22
|
+
};
|
@@ -0,0 +1,260 @@
|
|
1
|
+
import { EasJsonAccessor, EasJsonUtils, Platform } from '@expo/eas-json';
|
2
|
+
import { type Props, print } from 'bluebun';
|
3
|
+
import { $ } from 'bun';
|
4
|
+
|
5
|
+
export interface MobileProps extends Props {
|
6
|
+
options: {
|
7
|
+
profile: string;
|
8
|
+
platform: Platform.IOS | Platform.ANDROID;
|
9
|
+
jsEngine?: 'hermes' | 'jsc';
|
10
|
+
debug?: boolean;
|
11
|
+
};
|
12
|
+
}
|
13
|
+
|
14
|
+
async function needsBinary(lib: string) {
|
15
|
+
const whichLib = await $`which ${lib}`.text();
|
16
|
+
return whichLib.includes('not found');
|
17
|
+
}
|
18
|
+
|
19
|
+
async function needsBrewFormula(formula: string) {
|
20
|
+
return (await $`brew list --formula | grep ${formula} | wc -l`.text()).trim() === '0';
|
21
|
+
}
|
22
|
+
|
23
|
+
export async function setup({
|
24
|
+
props,
|
25
|
+
env: envOpts,
|
26
|
+
}: {
|
27
|
+
props: MobileProps;
|
28
|
+
env?: Partial<typeof Bun.env>;
|
29
|
+
}) {
|
30
|
+
const { profile, platform, jsEngine = 'hermes', debug = false } = props.options;
|
31
|
+
|
32
|
+
/* -------------------------------------------------------------------------- */
|
33
|
+
/* HOMEBREW SETUP */
|
34
|
+
/* -------------------------------------------------------------------------- */
|
35
|
+
const needsBrew = await needsBinary('brew');
|
36
|
+
if (needsBrew) {
|
37
|
+
console.log('Installing brew...');
|
38
|
+
await $`/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`;
|
39
|
+
console.log('Installing brew...Complete');
|
40
|
+
|
41
|
+
/**
|
42
|
+
* This portion of logic was ported from the homebrew installer script
|
43
|
+
* https://github.com/Homebrew/install/blob/master/install.sh#L153C5-L153C63.
|
44
|
+
* However, their script just alerts users to the fact that they need to add
|
45
|
+
* brew to their path, but doesn't do it for them. This logic attempts to do that
|
46
|
+
* so we can automatically proceed to the next steps of auto-installing
|
47
|
+
* the necessary dependencies for local development.
|
48
|
+
*/
|
49
|
+
const machineArch = await $`uname -m`.text();
|
50
|
+
const isLinux = (await $`uname`.text()) === 'Linux';
|
51
|
+
const shellType = await $`echo $SHELL`.text();
|
52
|
+
const homebrewPrefix = machineArch.includes('arm64') ? '/opt/homebrew' : '/usr/local';
|
53
|
+
let shellRcFile;
|
54
|
+
|
55
|
+
if (isLinux) {
|
56
|
+
shellRcFile = shellType.includes('zsh') ? '.zshrc' : '.bashrc';
|
57
|
+
} else {
|
58
|
+
shellRcFile = shellType.includes('zsh') ? '.zprofile' : '.bash_profile';
|
59
|
+
}
|
60
|
+
|
61
|
+
const shellRcPath = `${Bun.env.HOME}/${shellRcFile}`;
|
62
|
+
let shellRcContents = '';
|
63
|
+
try {
|
64
|
+
shellRcContents = await Bun.file(shellRcPath).text();
|
65
|
+
} catch (err) {
|
66
|
+
// Ignore if it doesn't exist. We create it below.
|
67
|
+
}
|
68
|
+
|
69
|
+
if (!shellRcContents.includes('homebrew')) {
|
70
|
+
console.log('Adding brew to $PATH...');
|
71
|
+
const newShellRcContents = `${shellRcContents}\neval "$(${homebrewPrefix}/bin/brew shellenv)"`;
|
72
|
+
await Bun.write(shellRcPath, newShellRcContents);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
/* -------------------------------------------------------------------------- */
|
77
|
+
/* FASTLANE SETUP */
|
78
|
+
/* -------------------------------------------------------------------------- */
|
79
|
+
const needsFastlane = await needsBrewFormula('fastlane');
|
80
|
+
if (needsFastlane) {
|
81
|
+
console.log('Installing fastlane...');
|
82
|
+
await $`brew install fastlane`;
|
83
|
+
}
|
84
|
+
|
85
|
+
/* -------------------------------------------------------------------------- */
|
86
|
+
/* COCOAPODS SETUP */
|
87
|
+
/* -------------------------------------------------------------------------- */
|
88
|
+
const needsCocoapods = await needsBrewFormula('cocoapods');
|
89
|
+
if (needsCocoapods) {
|
90
|
+
console.log('Installing cocoapods...');
|
91
|
+
await $`brew install cocoapods`;
|
92
|
+
}
|
93
|
+
|
94
|
+
/* -------------------------------------------------------------------------- */
|
95
|
+
/* JAVA DEVELOPMENT KIT */
|
96
|
+
/* -------------------------------------------------------------------------- */
|
97
|
+
if (platform === 'android') {
|
98
|
+
const jdkPath = await $`brew info --cask zulu17`.text();
|
99
|
+
const needsJdk = jdkPath.includes('unavailable');
|
100
|
+
if (needsJdk) {
|
101
|
+
console.log('Installing Java Development Kit for Android...');
|
102
|
+
await $`brew install --cask zulu17`;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
/* -------------------------------------------------------------------------- */
|
107
|
+
/* EXPO SETUP */
|
108
|
+
/* -------------------------------------------------------------------------- */
|
109
|
+
const appDirectory = Bun.env.PWD;
|
110
|
+
const easJsonAccessor = EasJsonAccessor.fromProjectPath(appDirectory);
|
111
|
+
|
112
|
+
const easProfiles = await EasJsonUtils.getBuildProfileNamesAsync(easJsonAccessor);
|
113
|
+
|
114
|
+
if (!easProfiles.includes(profile)) {
|
115
|
+
const profileNames = easProfiles.join(', ');
|
116
|
+
const suggestion = `Please add one or use ${profileNames}.`;
|
117
|
+
|
118
|
+
if (!profile) {
|
119
|
+
print(`No profile name was provided. ${suggestion}`);
|
120
|
+
} else {
|
121
|
+
print(
|
122
|
+
`A profile with name ${profile} does not exist as a key in eas.json > build object.\n${suggestion}`,
|
123
|
+
);
|
124
|
+
}
|
125
|
+
process.exit(0);
|
126
|
+
}
|
127
|
+
|
128
|
+
const easJsonConfig = await EasJsonUtils.getBuildProfileAsync(easJsonAccessor, platform, profile);
|
129
|
+
|
130
|
+
const easCliConfig = await EasJsonUtils.getCliConfigAsync(easJsonAccessor);
|
131
|
+
const easCliVersion = easCliConfig?.version ?? 'latest';
|
132
|
+
|
133
|
+
/* -------------------------------------------------------------------------- */
|
134
|
+
/* EAS CLI SETUP */
|
135
|
+
/* -------------------------------------------------------------------------- */
|
136
|
+
const needsEasCli = await needsBinary('eas');
|
137
|
+
if (needsEasCli) {
|
138
|
+
await $`bun install eas-cli@${easCliVersion} -g`;
|
139
|
+
} else {
|
140
|
+
const currentEasCliVersion = await $`eas --version`.text();
|
141
|
+
if (currentEasCliVersion !== easCliVersion) {
|
142
|
+
await $`bun install eas-cli@${easCliVersion} -g`;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
const {
|
147
|
+
APP_BUNDLE_IDENTIFIER,
|
148
|
+
APP_ANDROID_BUNDLE_IDENTIFIER: androidId = APP_BUNDLE_IDENTIFIER as string,
|
149
|
+
APP_APPLE_BUNDLE_IDENTIFIER: appleId = APP_BUNDLE_IDENTIFIER as string,
|
150
|
+
} = easJsonConfig.env ?? {};
|
151
|
+
|
152
|
+
// TODO: Add additional checks for ensuring this value adheres to Android formatting specs
|
153
|
+
if (platform === Platform.ANDROID && !androidId) {
|
154
|
+
throw new Error(`
|
155
|
+
APP_ANDROID_BUNDLE_IDENTIFIER must be defined in eas.json within the ${profile} > env config.
|
156
|
+
See https://docs.expo.dev/build-reference/variables/#setting-plaintext-environment-variables-in-easjson for information about env variables in eas.json
|
157
|
+
|
158
|
+
This env variable is used to populate the package key in your app.config.(js|ts) > android
|
159
|
+
The format of this env variable must use DNS notation unique name for your app, which is a valid Android Application ID.
|
160
|
+
|
161
|
+
For example you could use, com.company.app, where com.company is our domain and app is our app.
|
162
|
+
|
163
|
+
We recommend having the release build use the simplest identifier such as com.company.app and your debug variants
|
164
|
+
adding additional context such as com.company.app_debug. When publishing, the release identifier must be unique on the Play Store.
|
165
|
+
|
166
|
+
The name may only contain lowercase and uppercase letters (a-z, A-Z), numbers (0-9) and underscores (_),
|
167
|
+
separated by periods (.). Each component of the name should start with a lowercase letter.
|
168
|
+
|
169
|
+
These formatting rules only applies to Android. iOS has different requirements.
|
170
|
+
|
171
|
+
See https://docs.expo.dev/versions/latest/config/app/#package for more details on formatting.
|
172
|
+
See https://docs.expo.dev/build-reference/variants/ for information about build variants.
|
173
|
+
`);
|
174
|
+
}
|
175
|
+
|
176
|
+
// TODO: Add additional checks for ensuring this value adheres to Uniform Type Identifier
|
177
|
+
if (platform === Platform.IOS && !appleId) {
|
178
|
+
throw new Error(`
|
179
|
+
APP_APPLE_BUNDLE_IDENTIFIER must be defined in eas.json within the ${profile} > env config.
|
180
|
+
See https://docs.expo.dev/build-reference/variables/#setting-plaintext-environment-variables-in-easjson for information about env variables in eas.json
|
181
|
+
|
182
|
+
This env variable is used to populate the package key in your app.config.(js|ts) > ios
|
183
|
+
The format of this env variable must use DNS notation unique name for your app, which is a valid Android Application ID.
|
184
|
+
|
185
|
+
For example you could use, com.company.app, where com.company is our domain and app is our app.
|
186
|
+
|
187
|
+
We recommend having the release build use the simplest identifier such as com.company.app and your debug variants
|
188
|
+
adding additional context such as com.company.app-debug. When publishing, the release identifier must be unique to the App Store.
|
189
|
+
|
190
|
+
The string format should be Uniform Type Identifier(UTI), which is alphanumeric characters (A-Z,a-z,0-9), hyphen (-), and period (.)
|
191
|
+
|
192
|
+
These formatting rules only applies to iOS. Android has different requirements.
|
193
|
+
|
194
|
+
See https://docs.expo.dev/versions/latest/config/app/#bundleidentifier for more details on formatting.
|
195
|
+
See https://docs.expo.dev/build-reference/variants/ for information about build variants.
|
196
|
+
`);
|
197
|
+
}
|
198
|
+
|
199
|
+
const outputName = `${platform}-${profile}-${jsEngine}`;
|
200
|
+
// TODO: make this configurable
|
201
|
+
const prebuildsDir = `${appDirectory}/prebuilds`;
|
202
|
+
const outputDir = `${prebuildsDir}/${outputName}`;
|
203
|
+
const outputFileBase = `${outputDir}/${outputName}`;
|
204
|
+
|
205
|
+
let envVars = Bun.env;
|
206
|
+
|
207
|
+
envVars = {
|
208
|
+
...envVars,
|
209
|
+
APP_ANDROID_BUNDLE_IDENTIFIER: androidId,
|
210
|
+
APP_APPLE_BUNDLE_IDENTIFIER: appleId,
|
211
|
+
RCT_NO_LAUNCH_PACKAGER: '1',
|
212
|
+
EXPO_NO_TELEMETRY: '1',
|
213
|
+
EXPO_NO_WEB_SETUP: '1',
|
214
|
+
};
|
215
|
+
|
216
|
+
if (debug) {
|
217
|
+
envVars = {
|
218
|
+
...envVars,
|
219
|
+
DEBUG: '*',
|
220
|
+
EAS_LOCAL_BUILD_SKIP_CLEANUP: '1',
|
221
|
+
EXPO_PROFILE: '1',
|
222
|
+
};
|
223
|
+
}
|
224
|
+
|
225
|
+
if (envOpts) {
|
226
|
+
envVars = { ...envVars, ...envOpts };
|
227
|
+
}
|
228
|
+
|
229
|
+
$.env(envVars);
|
230
|
+
|
231
|
+
const output = {
|
232
|
+
name: outputName,
|
233
|
+
dir: outputDir,
|
234
|
+
prebuildsDir: prebuildsDir,
|
235
|
+
fileBase: outputFileBase,
|
236
|
+
artifact: platform === 'ios' ? `${outputFileBase}.tar.gz` : `${outputFileBase}.zip`,
|
237
|
+
app: platform === 'ios' ? `${outputFileBase}.app` : 'todo fix android',
|
238
|
+
get launchFile() {
|
239
|
+
return platform === 'ios' ? this.artifact : this.apk.signed;
|
240
|
+
},
|
241
|
+
apk: {
|
242
|
+
contents: `${outputFileBase}/build`,
|
243
|
+
rebuilt: `${outputFileBase}/binary-rebuilt.apk`,
|
244
|
+
rebuiltAligned: `${outputFileBase}/binary-rebuilt-aligned.apk`,
|
245
|
+
signed: `${outputFileBase}/binary.apk`,
|
246
|
+
test: `${outputFileBase}/testBinary.apk`,
|
247
|
+
},
|
248
|
+
};
|
249
|
+
|
250
|
+
return {
|
251
|
+
scheme: platform === 'ios' ? appleId : androidId,
|
252
|
+
channel: easJsonConfig.channel,
|
253
|
+
debug,
|
254
|
+
profile,
|
255
|
+
platform,
|
256
|
+
jsEngine,
|
257
|
+
appDirectory,
|
258
|
+
output,
|
259
|
+
};
|
260
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { $ } from 'bun';
|
2
|
+
import type { MobileProps } from './_setup';
|
3
|
+
import { setup } from './_setup';
|
4
|
+
|
5
|
+
export default {
|
6
|
+
name: 'build',
|
7
|
+
description: '🚀 Build',
|
8
|
+
run: async (props: MobileProps) => {
|
9
|
+
const { platform, profile, output } = await setup({
|
10
|
+
props,
|
11
|
+
});
|
12
|
+
|
13
|
+
await $`eas build --local --non-interactive --json --clear-cache --platform ${platform} --profile ${profile} --output ${output.artifact}`;
|
14
|
+
},
|
15
|
+
};
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import { Props } from 'bluebun';
|
2
|
+
import { $ } from 'bun';
|
3
|
+
import { setup, type MobileProps } from './_setup';
|
4
|
+
|
5
|
+
interface MobileStartProps extends Props {
|
6
|
+
options: MobileProps['options'] & {
|
7
|
+
// Clear the cache when starting dev server
|
8
|
+
clear?: boolean;
|
9
|
+
};
|
10
|
+
}
|
11
|
+
|
12
|
+
type SimDevice = { udid: string; name: string; state: 'Booted' | 'Shutdown' };
|
13
|
+
type SimList = {
|
14
|
+
devices: {
|
15
|
+
['com.apple.CoreSimulator.SimRuntime.iOS-17-2']: SimDevice[];
|
16
|
+
};
|
17
|
+
};
|
18
|
+
|
19
|
+
export default {
|
20
|
+
name: 'dev',
|
21
|
+
description: '🚧 Dev',
|
22
|
+
run: async (props: MobileStartProps) => {
|
23
|
+
console.log('running dev');
|
24
|
+
const { platform, scheme, output } = await setup({
|
25
|
+
props,
|
26
|
+
env: {
|
27
|
+
EXPO_USE_METRO_WORKSPACE_ROOT: '1',
|
28
|
+
},
|
29
|
+
});
|
30
|
+
|
31
|
+
if (platform === 'ios') {
|
32
|
+
const xcodePath = await $`xcode-select -p`.text();
|
33
|
+
const xcodeExists = xcodePath.startsWith('/Applications');
|
34
|
+
|
35
|
+
if (xcodeExists) {
|
36
|
+
await $`open -a simulator`;
|
37
|
+
const deviceList = (await $`xcrun simctl list devices available -j -e`.json()) as SimList;
|
38
|
+
|
39
|
+
const devices = Object.values(deviceList?.devices).flatMap((item) => item);
|
40
|
+
|
41
|
+
if (devices.length === 0) {
|
42
|
+
throw new Error('No devices found');
|
43
|
+
} else {
|
44
|
+
const isBooted = devices.find((device: SimDevice) => device.state === 'Booted');
|
45
|
+
if (!isBooted) {
|
46
|
+
const iphone15Max = devices.find(
|
47
|
+
(device: SimDevice) => device.name === 'iPhone 15 Pro Max',
|
48
|
+
);
|
49
|
+
if (!iphone15Max) {
|
50
|
+
throw new Error('iPhone 15 Pro Max not found');
|
51
|
+
} else {
|
52
|
+
const udid = iphone15Max.udid;
|
53
|
+
await $`xcrun simctl boot ${udid}`;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
} else {
|
58
|
+
console.log(
|
59
|
+
'You must have XCode installed before continuing... Visit https://apps.apple.com/us/app/xcode/id497799835?mt=12 to download.',
|
60
|
+
);
|
61
|
+
throw new Error('XCode not installed');
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
await $`eas build:run --platform ${platform} --path ${output.launchFile}`;
|
66
|
+
|
67
|
+
const extraArgs = [];
|
68
|
+
|
69
|
+
if (props.options.clear) {
|
70
|
+
extraArgs.push('--clear');
|
71
|
+
}
|
72
|
+
|
73
|
+
const extrArgsString = extraArgs.join(' ');
|
74
|
+
|
75
|
+
console.log(`Starting metro server...`);
|
76
|
+
|
77
|
+
await $`expo start --${platform} --dev-client --localhost --scheme ${scheme} ${extrArgsString}`;
|
78
|
+
},
|
79
|
+
};
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { type Props } from 'bluebun';
|
2
|
+
import { getCommandHelp } from '../../utils/getCommandHelp';
|
3
|
+
|
4
|
+
export default {
|
5
|
+
name: 'expo',
|
6
|
+
description: '',
|
7
|
+
run: async (props: Props) => {
|
8
|
+
switch (props?.first) {
|
9
|
+
case 'build':
|
10
|
+
return require('./build').default.run(props);
|
11
|
+
case 'dev':
|
12
|
+
return require('./dev').default.run(props);
|
13
|
+
case 'launch':
|
14
|
+
return require('./launch').default.run(props);
|
15
|
+
case 'update':
|
16
|
+
return require('./update').default.run(props);
|
17
|
+
default: {
|
18
|
+
await getCommandHelp(props);
|
19
|
+
break;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
},
|
23
|
+
};
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { $ } from 'bun';
|
2
|
+
import type { MobileProps } from './_setup';
|
3
|
+
import { setup } from './_setup';
|
4
|
+
|
5
|
+
export default {
|
6
|
+
name: 'launch',
|
7
|
+
description: '🚀 Launch',
|
8
|
+
run: async (props: MobileProps) => {
|
9
|
+
const { platform, output } = await setup({
|
10
|
+
props,
|
11
|
+
});
|
12
|
+
|
13
|
+
await $`eas build:run --platform ${platform} --path ${output.launchFile}`;
|
14
|
+
},
|
15
|
+
};
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { $ } from 'bun';
|
2
|
+
import type { MobileProps } from './_setup';
|
3
|
+
import { setup } from './_setup';
|
4
|
+
|
5
|
+
export default {
|
6
|
+
name: 'update',
|
7
|
+
description: '🚀 Update',
|
8
|
+
run: async (props: MobileProps) => {
|
9
|
+
const { channel } = await setup({
|
10
|
+
props,
|
11
|
+
});
|
12
|
+
|
13
|
+
await $`eas update --auto --channel ${channel}`;
|
14
|
+
await $`rm -rf dist`;
|
15
|
+
},
|
16
|
+
};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { setupConfigWorker } from '../../utils/setupConfigWorker';
|
2
|
+
import { Props } from 'bluebun';
|
3
|
+
import { SyncOptions } from '../../utils/types';
|
4
|
+
import { $ } from 'bun';
|
5
|
+
|
6
|
+
interface DevProps extends Props {
|
7
|
+
options: SyncOptions;
|
8
|
+
}
|
9
|
+
|
10
|
+
export default {
|
11
|
+
name: 'dev',
|
12
|
+
description: '🚧 Dev',
|
13
|
+
run: async ({ options }: DevProps) => {
|
14
|
+
await setupConfigWorker(options);
|
15
|
+
await $`next dev`;
|
16
|
+
},
|
17
|
+
};
|
package/cli/env.d.ts
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
declare module 'bun' {
|
2
|
+
interface Env {
|
3
|
+
PWD: string;
|
4
|
+
APP_APPLE_BUNDLE_IDENTIFIER: string;
|
5
|
+
APP_ANDROID_BUNDLE_IDENTIFIER: string;
|
6
|
+
RCT_NO_LAUNCH_PACKAGER?: string;
|
7
|
+
EXPO_NO_TELEMETRY?: string;
|
8
|
+
EAS_LOCAL_BUILD_ARTIFACTS_DIR?: string;
|
9
|
+
EAS_LOCAL_BUILD_SKIP_CLEANUP?: string;
|
10
|
+
EXPO_PROFILE?: string;
|
11
|
+
EXPO_USE_METRO_WORKSPACE_ROOT?: string;
|
12
|
+
EXPO_BUNDLE_APP?: string;
|
13
|
+
ESLINT_USE_FLAT_CONFIG?: string;
|
14
|
+
}
|
15
|
+
}
|