@chronsyn/eas-on-infra 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.example ADDED
@@ -0,0 +1,11 @@
1
+ # Server - add the following to .env file in this repo
2
+ PORT=3000
3
+ SITE_BASE_URL=https://builder-mac.example.com
4
+
5
+ # Server - optional
6
+ EXTRACT_DIRECTORY=/path/to/your/binary-output-directory
7
+ BINARY_OUTPUT_DIRECTORY=/path/to/your/binary-output-directory
8
+ UPLOAD_DIRECTORY=/path/to/your/upload-directory
9
+
10
+ # REQUIRED - Client - in your Expo project directory, add the following to your env file
11
+ ELB_EAS_ACCESS_TOKEN=your-eas-access-token-here
package/README.md ADDED
@@ -0,0 +1,191 @@
1
+ # EAS on-infra
2
+
3
+ A self-hosted EAS build CLI designed to offload builds to a remote system.
4
+
5
+ This is a tool designed to wrap the EAS CLI on your own hardware, and expose a set of endpoints to enable functionality such as building.
6
+
7
+ ## Project status
8
+
9
+ This project is currently in beta status. It should mostly work, but there may be bugs.
10
+
11
+ ## Requirements - Hardware
12
+
13
+ Your requirements may vary, but I recommend the following setup if you intend to build iOS apps (can also build Android apps):
14
+
15
+ - Mac Mini featuring at least an M1 chip
16
+ - Note: The M1 is likely to be deprecated for updates in a few years, so a more recent model such as M4 or M5 is advised for longer-term support
17
+ - 32GB RAM minimum (24GB might be manageable, but I don't recommend less than 32GB)
18
+ - 1TB internal storage recommended (512GB may be sufficient)
19
+
20
+ If you intend to run this for many projects, create many builds, or you're serving a business or office environment, I recommend the following additional:
21
+
22
+ - An external storage drive, 2TB or greater
23
+
24
+ If you're only building Android apps, you should be able to run this on a Windows or Linux system, but these setups are not tested.
25
+
26
+ ## Requirements - Software (build server)
27
+
28
+ The following tools are required to be installed and configured on the build server. The list below is assuming you're using a Mac as the build server:
29
+
30
+ - NodeJS
31
+ - I recommend using[NVM (Node Version Manager)](https://github.com/nvm-sh/nvm) as this can help keep your version up to date
32
+ - Make sure to `nvm install` (followed by a version number) after installing NVM
33
+ - EAS CLI (`npm install -g eas-cli`)
34
+ - Homebrew (tooling installation) (`/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`)
35
+ - Fastlane (iOS builds) (`brew install fastlane`)
36
+ - Cocoapods (iOS builds) (`brew install cocoapods`)
37
+ - Java (Android builds) (`brew install openjdk@17`)
38
+ - Android Studio (Android builds) (Download here: https://developer.android.com/studio )
39
+
40
+ **Note**: The commands above may not be the most up-to-date when you read this. For example, Java/OpenJDK might need a newer version. I recommend Googling to check for the latest info.
41
+
42
+ You must ensure that you go through any necessary configuration for these tools before attempting to build.
43
+ For example, with Android Studio, you will likely have to install the build tools from within Android studio, and perhaps agree to licenses. You also probably need to set things like `ANDROID_HOME` variables - Google how to do this because it's outside the scope of this readme.
44
+
45
+ Additional tooling below is required only if you need third-party installers (see official docs for most recent commands):
46
+
47
+ - Yarn (`npm install -g yarn`)
48
+ - Bun (`curl -fsSL https://bun.com/install | bash`)
49
+ - Pnpm (`npm install -g pnpm@latest-10` or `brew install pnpm`)
50
+
51
+ For convenience, I also recommend the following if you're on a Mac:
52
+
53
+ - [XCodes](https://xcodes.app) - This makes it easier to manage Xcode versions and keep up to date with the latest version
54
+
55
+ Once you've configured the tooling, I recommend trying to run a build using a locally cloned version of a project (or creating a fresh Expo project), as this can often help identify if there are configuration issues.
56
+
57
+ ## Project requirements
58
+
59
+ In order to create builds using this tool, you must ensure that your project is already configured with EAS, and that certificates and profiles have been provisioned. This is because this tool runs in non-interactive mode on the server.
60
+
61
+ You will also need to ensure you have create an EAS access token.
62
+
63
+ You will also need to create an env file of some sort in your project, as you will need to add your EAS access token to it. See below for more information.
64
+
65
+ ## Setup - Server
66
+
67
+ On the system which will be running the build, close this repo and run `yarn` from the directory to install dependencies. Alternatively, you can install it globally on the server with:
68
+
69
+ ```sh
70
+ npm install -g @chronsyn/eas-on-infra
71
+ ```
72
+ **Note**: If you choose to install it globally, you will not be able to make use of a .env file on the server, but you can still pass env variables to it using typical platform methods.
73
+
74
+ Then, create a `.env` file (or specify manually) with the following variables:
75
+ - `PORT` (number, which port the server will accept requests on, defaults to 3000 if not specified)
76
+ - `SITE_BASE_URL` (string/text, the URL where your builder is running. This could be the device IP if you don't have a domain setup for it)
77
+
78
+ Note: `SITE_BASE_URL` is currently only used to output a status URL, but the status URL itself isn't yet implemented.
79
+ This will be added in a future version.
80
+
81
+ You can also specify the following optional fields:
82
+
83
+ - `EXTRACT_DIRECTORY` (string/text - the directory where files will be extracted - note: a unique subdirectory will be created for each upload)
84
+ - `BINARY_OUTPUT_DIRECTORY` (string/text - the directory where built app binaries will be output)
85
+ - `UPLOAD_DIRECTORY` (string/text - the directory where zip files will be uploaded)
86
+
87
+ By default, the `extracted`, `builds`, and `uploads` directories within this project will be used if any of the above aren't specified.
88
+
89
+ If you cloned the repo, run `yarn start` . Your server is now running and ready to start builds.
90
+ Alternatively, run `npx eas-on-infra serve`.
91
+
92
+ ## Setup - local system (e.g. your laptop where the code is available)
93
+
94
+ In this context, the local system would be any system where the Expo project code is available - for example, a laptop that is used to develop the code.
95
+
96
+ - Add your Expo access token to your dotenv file (`ELB_EAS_ACCESS_TOKEN=<your access token>`)
97
+ - Ensure you have configured your project to build (`eas build:configure` => `eas build --profile <profile> --platform <platform>`, then follow any instructions. You can cancel the process when you see 'Uploading to EAS' to prevent the build from running).
98
+
99
+ Then, run:
100
+
101
+ ```sh
102
+ npx eas-on-infra build --profile production --platform ios --config_file_path .env --build_server http://address-of-your-build-server
103
+ ```
104
+ NPM / NPX might be prompt you to install the library - press `y` if you're happy to continue.
105
+
106
+ After that, your project will be zipped up (excluding `node_modules`), and sent to the build server.
107
+
108
+ ## Command flags
109
+
110
+ ### `--profile`
111
+ - **Required**: Yes
112
+ - **What**: A build profile which is specified in your `eas.json` file
113
+ - **Note**: In a future version, you will be able to define specific profile names which are allowed
114
+
115
+ ### `--platform`
116
+ - **Required**: Yes
117
+ - **What**: Which platform are you building for
118
+ - **Valid options**: `ios`, `android`
119
+ - **Note**: The `all` option is not supported, but you may be able to run both Android and iOS builds at the same time
120
+
121
+ ### `--config_file_path`
122
+ - **Required**: No
123
+ - **What**: The filename (not the file path) to the env file you want to use with the project. For example, `.env`, `.env.local`, etc.
124
+ - **Why**: In case you want to use a specific config file with the build - useful to create bespoke builds that aren't linked to standard environments.
125
+ - **Default value**: None
126
+ - **Note**: The env file you want to include should be located in the root of the project. Other `.env` files will be excluded from the bundle. If this flag is not specified, all `.env` files will be excluded.
127
+
128
+ ### `--installer`
129
+ - **Required**: No
130
+ - **What**: Which tool you want to use to install the project dependencies
131
+ - **Valid options**: `npm`, `yarn`, `bun`, `pnpm`
132
+ - **Default value**: `npm`
133
+ - **Note**: This will run the appropriate installation command for the tool you specify
134
+
135
+ ### `--build_server`
136
+ - **Required**: Yes
137
+ - **What**: The base URL of your build server
138
+ - **Example**: if your build server is running at `192.168.1.25` on port `3000`, this would be `http://192.168.1.25:3000`
139
+
140
+
141
+ ## Bug reports
142
+
143
+ As this project is based primarily around EAS CLI, issues you experience can often be resolved in the same way you'd resolve them if using EAS locally or on the official Expo EAS servers.
144
+
145
+ Bug reports are still accepted, but the following types of issues will be closed (list is non-exhaustive):
146
+
147
+ - 'Will this run on <computer>?' (Try it and find out for yourself)
148
+ - 'I received <error> help!' (Google the error message)
149
+ - 'It didn't use the latest CLI version!' (You're resposible for managing the infra and tooling)
150
+ - 'Where's the publish command?' (This isn't an update publishing server)
151
+ - Anything that's not explicitly related to this tool
152
+
153
+ If you experience issues:
154
+
155
+ - Scroll through the logs and read what it says
156
+ - Google error messages
157
+
158
+ ## Why build this?
159
+
160
+ I typically work across multiple systems with various different operating systems, with code stored on one central system, and using SSH to access it.
161
+
162
+ One problem is that if the central system isn't a mac, I can't build iOS apps due to Apple's restrictions and requirements. I felt it was time to resolve that issue, but without explicitly requiring me to host the projects on a mac.
163
+
164
+ So, say hello to 'EAS on-infra'.
165
+
166
+ ## How does it work?
167
+
168
+ It's really just a simple REST API with only a few endpoints.
169
+ The `/ingress` POST endpoint accepts a zip file and some other fields.
170
+
171
+ The server extracts the zip, runs `npm i` to install dependencies for the project (can be customised to use yarn, bun, or pnpm), and then attempts to run the `eas build` command on the extracted files (along with some relevant flags, such as `--profile`, `--platform`, and most importantly `--local` and `--non-interactive` and `--output`).
172
+
173
+ ## What doesn't this tool do?
174
+
175
+ This tool does **NOT** do any of the following:
176
+
177
+ - OS system updates
178
+ - Core build tool updates (e.g. xcode, android studio)
179
+ - CLI updates (e.g. eas-cli)
180
+ - Bypass build requirements (e.g. iOS builds still require the server part of this tool to be run on a Mac)
181
+ - Make dinner
182
+
183
+ ## Issue debugging
184
+
185
+ The following info might be useful if you experience issues
186
+
187
+ - **package.json was not found in the project directory***
188
+ Make sure your project is initialised with git (`git init`), all files are added (`git add .`), and commited (`git commit -m 'comment'`).
189
+
190
+ - **iOS builds: Distribution certificate with fingerprint <xxxxxx> hasn't been imported successfully**
191
+ [One possible solution](https://github.com/expo/eas-cli/issues/1331#issuecomment-2608534905)
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export declare const runServer: () => import("node:http").Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>;
3
+ //# sourceMappingURL=application.core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application.core.d.ts","sourceRoot":"","sources":["../src/application.core.ts"],"names":[],"mappings":";AAgBA,eAAO,MAAM,SAAS,yHAEpB,CAAA"}
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.runServer = void 0;
8
+ const express_1 = __importDefault(require("express"));
9
+ const dotenv_1 = __importDefault(require("dotenv"));
10
+ const ingress_1 = require("./ingress");
11
+ dotenv_1.default.config({});
12
+ const config = Object.assign({}, process.env);
13
+ const app = (0, express_1.default)();
14
+ (0, ingress_1.configureRoute)(app);
15
+ const runServer = () => app.listen(config.PORT, () => {
16
+ console.log(`App listening on ${config.PORT}`);
17
+ });
18
+ exports.runServer = runServer;
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../src/client/root.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __rest = (this && this.__rest) || function (s, e) {
4
+ var t = {};
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
6
+ t[p] = s[p];
7
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
8
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
9
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
10
+ t[p[i]] = s[p[i]];
11
+ }
12
+ return t;
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const yargs_1 = __importDefault(require("yargs"));
19
+ const helpers_1 = require("yargs/helpers");
20
+ const dotenv_1 = __importDefault(require("dotenv"));
21
+ const send_build_1 = require("./send-build");
22
+ const application_core_1 = require("../application.core");
23
+ dotenv_1.default.config();
24
+ const argv = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv)).parseSync();
25
+ const { $0, _ } = argv, restArgs = __rest(argv, ["$0", "_"]);
26
+ var ESubcommand;
27
+ (function (ESubcommand) {
28
+ ESubcommand["build"] = "build";
29
+ ESubcommand["serve"] = "serve";
30
+ ESubcommand["publish"] = "publish";
31
+ ESubcommand["submit"] = "submit";
32
+ ESubcommand["deploy"] = "deploy";
33
+ ESubcommand["login"] = "login";
34
+ ESubcommand["logout"] = "logout";
35
+ ESubcommand["open"] = "open";
36
+ ESubcommand["upload"] = "upload";
37
+ })(ESubcommand || (ESubcommand = {}));
38
+ const [subcommand] = _;
39
+ if (!subcommand) {
40
+ console.log(`You did not provide a command to run`);
41
+ process.exit(1);
42
+ }
43
+ switch (subcommand) {
44
+ case ESubcommand.build:
45
+ (0, send_build_1.runBuild)();
46
+ break;
47
+ case ESubcommand.serve:
48
+ (0, application_core_1.runServer)();
49
+ break;
50
+ default:
51
+ console.log(`The "${subcommand}" option is not implemented or not recognised.`);
52
+ break;
53
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export declare const runBuild: () => Promise<void>;
3
+ //# sourceMappingURL=send-build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-build.d.ts","sourceRoot":"","sources":["../../src/client/send-build.ts"],"names":[],"mappings":";AAoCA,eAAO,MAAM,QAAQ,qBAwKpB,CAAA"}
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __rest = (this && this.__rest) || function (s, e) {
4
+ var t = {};
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
6
+ t[p] = s[p];
7
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
8
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
9
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
10
+ t[p[i]] = s[p[i]];
11
+ }
12
+ return t;
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.runBuild = void 0;
19
+ const node_fs_1 = __importDefault(require("node:fs"));
20
+ const promises_1 = __importDefault(require("node:fs/promises"));
21
+ const node_path_1 = __importDefault(require("node:path"));
22
+ const node_crypto_1 = __importDefault(require("node:crypto"));
23
+ const node_fetch_1 = __importDefault(require("node-fetch"));
24
+ const form_data_1 = __importDefault(require("form-data"));
25
+ const archiver_1 = __importDefault(require("archiver"));
26
+ const yargs_1 = __importDefault(require("yargs"));
27
+ const helpers_1 = require("yargs/helpers");
28
+ const zod_1 = __importDefault(require("zod"));
29
+ const dotenv_1 = __importDefault(require("dotenv"));
30
+ dotenv_1.default.config();
31
+ const argv = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv)).parseSync();
32
+ const ZArgs = zod_1.default.object({
33
+ access_token: zod_1.default.string(),
34
+ profile: zod_1.default.string(),
35
+ platform: zod_1.default.enum(['ios', 'android']),
36
+ config_file_path: zod_1.default.string(),
37
+ build_server: zod_1.default.url(),
38
+ installer: zod_1.default.enum([
39
+ 'npm', // npm i
40
+ 'yarn', // yarn
41
+ 'bun', // bun install
42
+ 'pnpm', // pnpm install
43
+ ]).optional()
44
+ }).strict();
45
+ const { $0, _ } = argv, restArgs = __rest(argv, ["$0", "_"]);
46
+ const runBuild = async () => {
47
+ var _a, _b;
48
+ const parsedArgs = ZArgs.safeParse(Object.assign(Object.assign({}, restArgs), { access_token: (_b = (_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.ELB_EAS_ACCESS_TOKEN) !== null && _b !== void 0 ? _b : restArgs === null || restArgs === void 0 ? void 0 : restArgs.access_token }));
49
+ if (parsedArgs.error) {
50
+ throw new Error("Error processing command", { cause: parsedArgs.error });
51
+ }
52
+ // console.log(parsedArgs)
53
+ console.log("Zipping bundle...");
54
+ // Define a custome extension so we can still include zip files (in case user project has any in)
55
+ const bundleFileExtension = '.ELBZIP';
56
+ const bundleFileName = [new Date().getTime(), node_crypto_1.default.randomBytes(16).toString('hex'), bundleFileExtension].join('_');
57
+ const outputBundlePath = node_path_1.default.resolve(process.cwd(), bundleFileName);
58
+ const outputBundleStream = node_fs_1.default.createWriteStream(outputBundlePath);
59
+ const archive = (0, archiver_1.default)('zip', { zlib: { level: 9 } });
60
+ // Catch warnings
61
+ archive.on("warning", (err) => {
62
+ if (err.code === 'ENOENT') {
63
+ console.warn(err);
64
+ }
65
+ else {
66
+ throw err;
67
+ }
68
+ });
69
+ // Handle errors
70
+ archive.on("error", (err) => {
71
+ throw err;
72
+ });
73
+ // Pipe archive to file
74
+ archive.pipe(outputBundleStream);
75
+ const directories = (await promises_1.default.readdir(process.cwd(), { withFileTypes: true }))
76
+ .filter(ent => ent.isDirectory())
77
+ .map(ent => ent.name)
78
+ .filter(ent => {
79
+ const ignoredEntries = [
80
+ 'node_modules',
81
+ ];
82
+ return !ignoredEntries.includes(ent);
83
+ });
84
+ const rootDirFiles = (await promises_1.default.readdir(process.cwd(), { withFileTypes: true }))
85
+ .filter(ent => ent.isFile())
86
+ .map(ent => ent.name)
87
+ .filter(ent => {
88
+ var _a;
89
+ if ((_a = parsedArgs === null || parsedArgs === void 0 ? void 0 : parsedArgs.data) === null || _a === void 0 ? void 0 : _a.config_file_path) {
90
+ const fileIsEnvConfigFile = node_path_1.default.basename(parsedArgs.data.config_file_path);
91
+ // Include the config file the user specified
92
+ if (ent === fileIsEnvConfigFile) {
93
+ return true;
94
+ }
95
+ }
96
+ // Exclude other .env files
97
+ if (ent.includes(".env")) {
98
+ return false;
99
+ }
100
+ // Don't include any files which use the same extension as we use for our bundle
101
+ if (ent.includes(bundleFileExtension)) {
102
+ return false;
103
+ }
104
+ return true;
105
+ });
106
+ // console.log(JSON.stringify({directories, rootDirFiles, outputBundlePath}, null, 2))
107
+ for (const file of rootDirFiles) {
108
+ const filePath = node_path_1.default.resolve(process.cwd(), file);
109
+ archive.append(node_fs_1.default.createReadStream(filePath), { name: file });
110
+ }
111
+ for (const dir of directories) {
112
+ const dirPath = node_path_1.default.resolve(process.cwd(), dir);
113
+ archive.directory(dirPath, dir);
114
+ }
115
+ await archive.finalize();
116
+ outputBundleStream.on('close', async () => {
117
+ console.log("Bundle close!");
118
+ const formData = new form_data_1.default();
119
+ formData.append("bundle", node_fs_1.default.createReadStream(outputBundlePath));
120
+ formData.append("eas_profile", parsedArgs.data.profile);
121
+ formData.append("eas_platform", parsedArgs.data.platform);
122
+ formData.append("eas_access_token", parsedArgs.data.access_token);
123
+ formData.append("installer", parsedArgs.data.installer);
124
+ const request = await (0, node_fetch_1.default)(`${parsedArgs.data.build_server}/ingress`, {
125
+ method: 'POST',
126
+ body: formData,
127
+ // Note: node-fetch handles the headers automatically when using FormData
128
+ // But you might need to disable SSL verification if needed:
129
+ // agent: new (require('https').Agent)({ rejectUnauthorized: false })
130
+ });
131
+ const response = await request.json();
132
+ console.log(JSON.stringify(response, null, 2));
133
+ node_fs_1.default.rmSync(outputBundlePath);
134
+ // formData.append('bundle', {
135
+ // [Symbol.toStringTag]: 'file',
136
+ // name: bundleFileName,
137
+ // stream: () => fs.createReadStream(outputBundlePath)
138
+ // })
139
+ // formData.append('bundle', fileAsBlob, bundleFileName);
140
+ // formData.append("eas_profile", parsedArgs.data.profile);
141
+ // formData.append("eas_platform", parsedArgs.data.platform);
142
+ // formData.append("eas_access_token", parsedArgs.data.access_token);
143
+ // const url = [parsedArgs.data.build_server, 'ingress'].join('/');
144
+ // const options = {
145
+ // method: 'POST',
146
+ // headers: {
147
+ // 'Content-Type': 'multipart/form-data; boundary=---bundle'
148
+ // },
149
+ // body: formData
150
+ // }
151
+ // const request = await fetch(url, options)
152
+ });
153
+ outputBundleStream.on('end', () => {
154
+ console.log("Bundle end!");
155
+ });
156
+ // const fileAsBlob = await fs.openAsBlob(outputBundlePath);
157
+ // console.log(fileAsBlob);
158
+ // const formData = new FormData()
159
+ // formData.append("bundle", fs.createReadStream(outputBundlePath))
160
+ // // formData.append('bundle', {
161
+ // // [Symbol.toStringTag]: 'file',
162
+ // // name: bundleFileName,
163
+ // // stream: () => fs.createReadStream(outputBundlePath)
164
+ // // })
165
+ // // formData.append('bundle', fileAsBlob, bundleFileName);
166
+ // formData.append("eas_profile", parsedArgs.data.profile);
167
+ // formData.append("eas_platform", parsedArgs.data.platform);
168
+ // formData.append("eas_access_token", parsedArgs.data.access_token);
169
+ // const url = [parsedArgs.data.build_server, 'ingress'].join('/');
170
+ // const options = {
171
+ // method: 'POST',
172
+ // headers: {
173
+ // 'Content-Type': 'multipart/form-data; boundary=---bundle'
174
+ // },
175
+ // body: formData
176
+ // }
177
+ // const request = await fetch(url, options)
178
+ // fs.rmSync(outputBundlePath)
179
+ };
180
+ exports.runBuild = runBuild;
@@ -0,0 +1,3 @@
1
+ import express from 'express';
2
+ export declare const configureRoute: (app: express.Express) => void;
3
+ //# sourceMappingURL=ingress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingress.d.ts","sourceRoot":"","sources":["../src/ingress.ts"],"names":[],"mappings":"AAIA,OAAO,OAAO,MAAM,SAAS,CAAC;AAmB9B,eAAO,MAAM,cAAc,GAAI,KAAK,OAAO,CAAC,OAAO,SAsUlD,CAAA"}