@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 +11 -0
- package/README.md +191 -0
- package/dist/application.core.d.ts +3 -0
- package/dist/application.core.d.ts.map +1 -0
- package/dist/application.core.js +18 -0
- package/dist/client/root.d.ts +3 -0
- package/dist/client/root.d.ts.map +1 -0
- package/dist/client/root.js +53 -0
- package/dist/client/send-build.d.ts +3 -0
- package/dist/client/send-build.d.ts.map +1 -0
- package/dist/client/send-build.js +180 -0
- package/dist/ingress.d.ts +3 -0
- package/dist/ingress.d.ts.map +1 -0
- package/dist/ingress.js +264 -0
- package/package.json +46 -0
- package/src/application.core.ts +19 -0
- package/src/client/root.ts +43 -0
- package/src/client/send-build.ts +205 -0
- package/src/ingress.ts +350 -0
- package/tsconfig.json +33 -0
package/dist/ingress.js
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.configureRoute = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
|
9
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
10
|
+
const multer_1 = __importDefault(require("multer"));
|
|
11
|
+
const zod_1 = __importDefault(require("zod"));
|
|
12
|
+
const unzipper_1 = __importDefault(require("unzipper"));
|
|
13
|
+
const ZBodySchema = zod_1.default.object({
|
|
14
|
+
eas_access_token: zod_1.default.string(),
|
|
15
|
+
eas_profile: zod_1.default.string(),
|
|
16
|
+
eas_platform: zod_1.default.enum(['ios', 'android']),
|
|
17
|
+
installer: zod_1.default.enum([
|
|
18
|
+
'npm', // npm i
|
|
19
|
+
'yarn', // yarn
|
|
20
|
+
'bun', // bun install
|
|
21
|
+
'pnpm', // pnpm install
|
|
22
|
+
]).optional()
|
|
23
|
+
}).strict();
|
|
24
|
+
const configureRoute = (app) => {
|
|
25
|
+
const multerDestination = !!process.env.UPLOAD_DIRECTORY
|
|
26
|
+
? node_path_1.default.resolve(process.env.UPLOAD_DIRECTORY)
|
|
27
|
+
: node_path_1.default.resolve(process.cwd(), 'uploads');
|
|
28
|
+
app.post('/ingress', (0, multer_1.default)({
|
|
29
|
+
limits: {
|
|
30
|
+
fileSize: 300000000, // 300MB
|
|
31
|
+
fieldNameSize: 8 * 50,
|
|
32
|
+
files: 1,
|
|
33
|
+
fields: 20,
|
|
34
|
+
},
|
|
35
|
+
preservePath: false,
|
|
36
|
+
storage: multer_1.default.diskStorage({
|
|
37
|
+
destination: multerDestination,
|
|
38
|
+
filename: (req, file, cb) => {
|
|
39
|
+
cb(null, [new Date().getTime(), node_crypto_1.default.randomBytes(16).toString('hex'), '.zip'].join('_'));
|
|
40
|
+
}
|
|
41
|
+
}),
|
|
42
|
+
fileFilter: (req, file, cb) => {
|
|
43
|
+
if (file.mimetype.toLowerCase() !== 'application/zip') {
|
|
44
|
+
return cb(new Error('File rejected'));
|
|
45
|
+
}
|
|
46
|
+
return cb(null, true);
|
|
47
|
+
},
|
|
48
|
+
}).single('bundle'), async (req, res, next) => {
|
|
49
|
+
var _a, _b, _c, _d;
|
|
50
|
+
console.log(`Received ingress request...`);
|
|
51
|
+
const actualInputFilePath = (_a = req.file) === null || _a === void 0 ? void 0 : _a.path;
|
|
52
|
+
const projectFileExtractName = [
|
|
53
|
+
new Date().getTime(),
|
|
54
|
+
node_crypto_1.default.randomBytes(4).toString("hex")
|
|
55
|
+
].join('_');
|
|
56
|
+
const extractedPath = node_path_1.default.resolve(process.env.BINARY_OUTPUT_DIRECTORY
|
|
57
|
+
? (process.env.BINARY_OUTPUT_DIRECTORY,
|
|
58
|
+
projectFileExtractName)
|
|
59
|
+
: (process.cwd(),
|
|
60
|
+
'extracted',
|
|
61
|
+
projectFileExtractName));
|
|
62
|
+
const directory = await unzipper_1.default.Open.file(actualInputFilePath);
|
|
63
|
+
await directory.extract({ path: extractedPath });
|
|
64
|
+
const parse = await ZBodySchema.safeParseAsync(req.body);
|
|
65
|
+
if (parse.error) {
|
|
66
|
+
res.status(500).json({ status: "error", error: parse.error });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const { eas_access_token,
|
|
70
|
+
// eas_project_id,
|
|
71
|
+
eas_platform, eas_profile, installer = 'npm' } = parse.data;
|
|
72
|
+
const build_id = node_crypto_1.default.randomBytes(16).toString('hex');
|
|
73
|
+
const fn = [
|
|
74
|
+
new Date().getTime(),
|
|
75
|
+
eas_platform,
|
|
76
|
+
eas_profile,
|
|
77
|
+
build_id
|
|
78
|
+
].join('__');
|
|
79
|
+
// If user has provided BINARY_OUTPUT_DIRECTORY in env, use that
|
|
80
|
+
// Else, fallback to output directory
|
|
81
|
+
const easBuildOutputPath = node_path_1.default.resolve(((_b = process === null || process === void 0 ? void 0 : process.env) === null || _b === void 0 ? void 0 : _b.BINARY_OUTPUT_DIRECTORY)
|
|
82
|
+
? ((_c = process === null || process === void 0 ? void 0 : process.env) === null || _c === void 0 ? void 0 : _c.BINARY_OUTPUT_DIRECTORY, fn)
|
|
83
|
+
: (process.cwd(), 'builds', fn));
|
|
84
|
+
console.log(`EXTRACTED PATH => ${extractedPath}`);
|
|
85
|
+
console.log(`BUILD OUTPUT PATH => ${easBuildOutputPath}`);
|
|
86
|
+
// const eas_auto_submit = parse.data.eas_auto_submit === "true";
|
|
87
|
+
let platformParsed;
|
|
88
|
+
switch (true) {
|
|
89
|
+
case eas_platform === "ios":
|
|
90
|
+
platformParsed = 'ios';
|
|
91
|
+
break;
|
|
92
|
+
case eas_platform === 'android':
|
|
93
|
+
platformParsed = 'android';
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
// TODO: chdir to directory, install dependencies
|
|
97
|
+
// TODO: check for `yarn.lock` to run `yarn install`, `package-lock.json` to run `npm i`, etc.
|
|
98
|
+
// const easBuildCommandWithArgs = [
|
|
99
|
+
// `git init &&`,
|
|
100
|
+
// `git add . &&`,
|
|
101
|
+
// `git commit -m "ready to build" &&`,
|
|
102
|
+
// `${builderToolToUse} &&`,
|
|
103
|
+
// `EXPO_TOKEN=${eas_access_token}`,
|
|
104
|
+
// 'eas build',
|
|
105
|
+
// '--profile', eas_profile.toString(),
|
|
106
|
+
// '--platform', eas_platform.toString(),
|
|
107
|
+
// '--local',
|
|
108
|
+
// '--non-interactive',
|
|
109
|
+
// '--output', `"${easBuildOutputPath}"`,
|
|
110
|
+
// ]
|
|
111
|
+
const easBinaryLocation = (0, node_child_process_1.execSync)(`which eas`, { encoding: 'utf-8' }).trim();
|
|
112
|
+
console.log("EAS BINARY => ", easBinaryLocation.toString());
|
|
113
|
+
// // All these are defined values - i.e. no user input
|
|
114
|
+
// // We're safe to exec them, as this also ensures steps are performed in the order expected
|
|
115
|
+
// try {
|
|
116
|
+
// execSync(`git init`)
|
|
117
|
+
// } catch (err) {
|
|
118
|
+
// console.error("Error with git init: ", err)
|
|
119
|
+
// }
|
|
120
|
+
// try {
|
|
121
|
+
// execSync(`git add .`);
|
|
122
|
+
// } catch (err) {
|
|
123
|
+
// console.error("Error with git add: ", err)
|
|
124
|
+
// }
|
|
125
|
+
// try {
|
|
126
|
+
// execSync(`git commit -m "ready to build"`);
|
|
127
|
+
// } catch (err) {
|
|
128
|
+
// console.error("Error with git commit: ", err)
|
|
129
|
+
// }
|
|
130
|
+
try {
|
|
131
|
+
switch (installer) {
|
|
132
|
+
case 'yarn':
|
|
133
|
+
(0, node_child_process_1.execSync)('yarn', {
|
|
134
|
+
stdio: 'inherit',
|
|
135
|
+
env: Object.assign(Object.assign({}, process.env), { PATH: process.env.PATH, EXPO_TOKEN: eas_access_token }),
|
|
136
|
+
});
|
|
137
|
+
break;
|
|
138
|
+
case 'bun':
|
|
139
|
+
(0, node_child_process_1.execSync)('bun install', {
|
|
140
|
+
stdio: 'inherit',
|
|
141
|
+
env: Object.assign(Object.assign({}, process.env), { PATH: process.env.PATH, EXPO_TOKEN: eas_access_token }),
|
|
142
|
+
});
|
|
143
|
+
break;
|
|
144
|
+
case "pnpm":
|
|
145
|
+
(0, node_child_process_1.execSync)('pnpm install', {
|
|
146
|
+
stdio: 'inherit',
|
|
147
|
+
env: Object.assign(Object.assign({}, process.env), { PATH: process.env.PATH, EXPO_TOKEN: eas_access_token }),
|
|
148
|
+
});
|
|
149
|
+
break;
|
|
150
|
+
case 'npm':
|
|
151
|
+
default:
|
|
152
|
+
(0, node_child_process_1.execSync)('npm i --force', {
|
|
153
|
+
stdio: 'inherit',
|
|
154
|
+
env: Object.assign(Object.assign({}, process.env), { PATH: process.env.PATH, EXPO_TOKEN: eas_access_token }),
|
|
155
|
+
});
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
console.error("Error with installer step: ", err);
|
|
161
|
+
}
|
|
162
|
+
process.chdir(extractedPath);
|
|
163
|
+
console.log(`Process cwd is now => `, process.cwd());
|
|
164
|
+
const easBuildArgs = [
|
|
165
|
+
`build`,
|
|
166
|
+
`--profile`, eas_profile.toString(),
|
|
167
|
+
`--platform`, eas_platform.toString(),
|
|
168
|
+
`--local`,
|
|
169
|
+
`--non-interactive`,
|
|
170
|
+
`--output`, easBuildOutputPath
|
|
171
|
+
];
|
|
172
|
+
// We run this with spawn as there's som user input
|
|
173
|
+
// We've sanitised it as much as possible, but we still want to minimise risk
|
|
174
|
+
const easBuildResult = (0, node_child_process_1.spawn)('eas', easBuildArgs, {
|
|
175
|
+
stdio: 'inherit',
|
|
176
|
+
shell: false,
|
|
177
|
+
env: Object.assign(Object.assign({}, process.env), { PATH: process.env.PATH, EXPO_TOKEN: eas_access_token }),
|
|
178
|
+
});
|
|
179
|
+
easBuildResult.on('error', (error) => {
|
|
180
|
+
console.error('Error spawning process:', error);
|
|
181
|
+
});
|
|
182
|
+
easBuildResult.on('close', (code, signal) => {
|
|
183
|
+
console.log(`Process exited with code ${code}, signal: ${signal === null || signal === void 0 ? void 0 : signal.toString()}`);
|
|
184
|
+
});
|
|
185
|
+
easBuildResult.on('message', (msg) => {
|
|
186
|
+
console.log(`Process msg: ${msg.toString()}`);
|
|
187
|
+
});
|
|
188
|
+
// easBuildResult.addListener('spawn', () => {
|
|
189
|
+
// console.log('[EAS BUILD] [SPAWN]')
|
|
190
|
+
// })
|
|
191
|
+
// easBuildResult.addListener('disconnect', () => {
|
|
192
|
+
// console.log('[EAS BUILD] [DISCONNECT]')
|
|
193
|
+
// })
|
|
194
|
+
// easBuildResult.addListener('error', (msg) => {
|
|
195
|
+
// console.log('[EAS BUILD] [ERROR]', msg.toString())
|
|
196
|
+
// })
|
|
197
|
+
// easBuildResult.addListener('exit', () => {
|
|
198
|
+
// console.log('[EAS BUILD] COMPLETED!')
|
|
199
|
+
// })
|
|
200
|
+
// easBuildResult.stdout.on('close', () => {
|
|
201
|
+
// console.log('[STDOUT] [EAS BUILD] CLOSE!')
|
|
202
|
+
// })
|
|
203
|
+
// easBuildResult.stdout.on('data', (msg) => {
|
|
204
|
+
// console.log('[STDOUT] [EAS BUILD]', msg)
|
|
205
|
+
// })
|
|
206
|
+
// easBuildResult.stdout.on('end', () => {
|
|
207
|
+
// console.log('[STDOUT] [EAS BUILD] END!')
|
|
208
|
+
// })
|
|
209
|
+
// easBuildResult.stdout.on('error', (err) => {
|
|
210
|
+
// console.log('[STDOUT] [ERR] [EAS BUILD] ', err.message)
|
|
211
|
+
// })
|
|
212
|
+
// easBuildResult.stdout.on('pause', () => {
|
|
213
|
+
// console.log('[STDOUT] [EAS BUILD] PAUSE!')
|
|
214
|
+
// })
|
|
215
|
+
// easBuildResult.stdout.on('readable', () => {
|
|
216
|
+
// console.log('[STDOUT] [EAS BUILD] READABLE!')
|
|
217
|
+
// })
|
|
218
|
+
// easBuildResult.stdout.on('resume', () => {
|
|
219
|
+
// console.log('[STDOUT] [EAS BUILD] RESUME!')
|
|
220
|
+
// })
|
|
221
|
+
// easBuildResult.stderr.on('close', () => {
|
|
222
|
+
// console.log('[STDERR] [EAS BUILD] CLOSE!')
|
|
223
|
+
// })
|
|
224
|
+
// easBuildResult.stderr.on('data', (msg) => {
|
|
225
|
+
// console.log('[STDERR] [EAS BUILD]', msg)
|
|
226
|
+
// })
|
|
227
|
+
// easBuildResult.stderr.on('end', () => {
|
|
228
|
+
// console.log('[STDERR] [EAS BUILD] END!')
|
|
229
|
+
// })
|
|
230
|
+
// easBuildResult.stderr.on('error', (err) => {
|
|
231
|
+
// console.log('[STDERR] [ERR] [EAS BUILD] ', err.message)
|
|
232
|
+
// })
|
|
233
|
+
// easBuildResult.stderr.on('pause', () => {
|
|
234
|
+
// console.log('[STDERR] [EAS BUILD] PAUSE!')
|
|
235
|
+
// })
|
|
236
|
+
// easBuildResult.stderr.on('readable', () => {
|
|
237
|
+
// console.log('[STDERR] [EAS BUILD] READABLE!')
|
|
238
|
+
// })
|
|
239
|
+
// easBuildResult.stderr.on('resume', () => {
|
|
240
|
+
// console.log('[STDERR] [EAS BUILD] RESUME!')
|
|
241
|
+
// })
|
|
242
|
+
// exec(
|
|
243
|
+
// easBuildCommandWithArgs,
|
|
244
|
+
// {
|
|
245
|
+
// cwd: extractedPath
|
|
246
|
+
// },
|
|
247
|
+
// (err, stdout, stderr) => {
|
|
248
|
+
// if (err) console.log('[ERR] => ', err);
|
|
249
|
+
// if (stdout) console.log('[STDOUT] => ', stdout);
|
|
250
|
+
// if (stderr) console.log('[STDERR] => ', stderr);
|
|
251
|
+
// }
|
|
252
|
+
// )
|
|
253
|
+
const responseData = {
|
|
254
|
+
ok: true,
|
|
255
|
+
status: 'in_progress',
|
|
256
|
+
build_id,
|
|
257
|
+
command: easBuildArgs,
|
|
258
|
+
status_url: `${((_d = process.env.SITE_BASE_URL) !== null && _d !== void 0 ? _d : "")}/status/${build_id}`,
|
|
259
|
+
};
|
|
260
|
+
console.log("Processing... Response => ", JSON.stringify(responseData, null, 2));
|
|
261
|
+
res.status(200).json(responseData);
|
|
262
|
+
});
|
|
263
|
+
};
|
|
264
|
+
exports.configureRoute = configureRoute;
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@chronsyn/eas-on-infra",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "dist/application.core.js",
|
|
5
|
+
"private": false,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "yarn tsc",
|
|
8
|
+
"serve": "node dist/application.core.js"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"eas-on-infra": "./dist/client/root.js"
|
|
12
|
+
},
|
|
13
|
+
"_developer_comments": {
|
|
14
|
+
"client_example_command": "npx eas-on-infra build --profile production --platform ios --installer npm --config_file_path .env --build_server http://192.168.1.25:3000"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [],
|
|
17
|
+
"author": "",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"description": "",
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/archiver": "^7.0.0",
|
|
22
|
+
"@types/express": "^5.0.6",
|
|
23
|
+
"@types/express-busboy": "^8.0.4",
|
|
24
|
+
"@types/express-fileupload": "^1.5.1",
|
|
25
|
+
"@types/multer": "^2.0.0",
|
|
26
|
+
"@types/node": "^25.0.2",
|
|
27
|
+
"@types/unzipper": "^0.10.11",
|
|
28
|
+
"@types/yargs": "^17.0.35",
|
|
29
|
+
"typescript": "^5.9.3"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@socialgouv/streaming-file-encryption": "^1.1.0",
|
|
33
|
+
"archiver": "^7.0.1",
|
|
34
|
+
"busboy": "^1.6.0",
|
|
35
|
+
"dotenv": "^17.2.3",
|
|
36
|
+
"express": "^5.2.1",
|
|
37
|
+
"express-busboy": "^10.1.0",
|
|
38
|
+
"express-fileupload": "^1.5.2",
|
|
39
|
+
"form-data": "^4.0.5",
|
|
40
|
+
"multer": "^2.0.2",
|
|
41
|
+
"node-fetch": "^3.3.2",
|
|
42
|
+
"unzipper": "^0.12.3",
|
|
43
|
+
"yargs": "^18.0.0",
|
|
44
|
+
"zod": "^4.2.1"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
4
|
+
|
|
5
|
+
import { configureRoute as postIngressRoute } from './ingress';
|
|
6
|
+
|
|
7
|
+
dotenv.config({})
|
|
8
|
+
|
|
9
|
+
const config = {
|
|
10
|
+
...process.env
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const app = express()
|
|
14
|
+
|
|
15
|
+
postIngressRoute(app)
|
|
16
|
+
|
|
17
|
+
export const runServer = () => app.listen(config.PORT, () => {
|
|
18
|
+
console.log(`App listening on ${config.PORT}`)
|
|
19
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import yargs from 'yargs';
|
|
3
|
+
import { hideBin } from 'yargs/helpers';
|
|
4
|
+
|
|
5
|
+
import dotenv from 'dotenv';
|
|
6
|
+
import { runBuild } from "./send-build";
|
|
7
|
+
import { runServer } from '../application.core';
|
|
8
|
+
dotenv.config()
|
|
9
|
+
|
|
10
|
+
const argv = yargs(hideBin(process.argv)).parseSync()
|
|
11
|
+
|
|
12
|
+
const { $0, _, ...restArgs } = argv;
|
|
13
|
+
|
|
14
|
+
enum ESubcommand {
|
|
15
|
+
build = "build",
|
|
16
|
+
serve = "serve",
|
|
17
|
+
publish = "publish",
|
|
18
|
+
submit = "submit",
|
|
19
|
+
deploy = "deploy",
|
|
20
|
+
login = "login",
|
|
21
|
+
logout = "logout",
|
|
22
|
+
open = "open",
|
|
23
|
+
upload = "upload",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const [ subcommand ] = _ as [ESubcommand];
|
|
27
|
+
|
|
28
|
+
if (!subcommand) {
|
|
29
|
+
console.log(`You did not provide a command to run`)
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
switch (subcommand) {
|
|
34
|
+
case ESubcommand.build:
|
|
35
|
+
runBuild()
|
|
36
|
+
break;
|
|
37
|
+
case ESubcommand.serve:
|
|
38
|
+
runServer()
|
|
39
|
+
break;
|
|
40
|
+
default:
|
|
41
|
+
console.log(`The "${subcommand}" option is not implemented or not recognised.`)
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import fsPromises from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import crypto from "node:crypto";
|
|
7
|
+
|
|
8
|
+
import fetch from "node-fetch";
|
|
9
|
+
|
|
10
|
+
import FormData from "form-data";
|
|
11
|
+
import archiver from "archiver";
|
|
12
|
+
|
|
13
|
+
import yargs from 'yargs';
|
|
14
|
+
import { hideBin } from 'yargs/helpers';
|
|
15
|
+
import z from 'zod';
|
|
16
|
+
|
|
17
|
+
import dotenv from 'dotenv';
|
|
18
|
+
dotenv.config()
|
|
19
|
+
|
|
20
|
+
const argv = yargs(hideBin(process.argv)).parseSync()
|
|
21
|
+
|
|
22
|
+
const ZArgs = z.object({
|
|
23
|
+
access_token: z.string(),
|
|
24
|
+
profile: z.string(),
|
|
25
|
+
platform: z.enum(['ios', 'android']),
|
|
26
|
+
config_file_path: z.string(),
|
|
27
|
+
build_server: z.url(),
|
|
28
|
+
installer: z.enum([
|
|
29
|
+
'npm', // npm i
|
|
30
|
+
'yarn', // yarn
|
|
31
|
+
'bun', // bun install
|
|
32
|
+
'pnpm', // pnpm install
|
|
33
|
+
]).optional()
|
|
34
|
+
}).strict()
|
|
35
|
+
const { $0, _, ...restArgs } = argv;
|
|
36
|
+
|
|
37
|
+
export const runBuild = async () => {
|
|
38
|
+
|
|
39
|
+
const parsedArgs = ZArgs.safeParse({
|
|
40
|
+
...restArgs,
|
|
41
|
+
access_token: process?.env?.ELB_EAS_ACCESS_TOKEN ?? restArgs?.access_token
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
if (parsedArgs.error) {
|
|
45
|
+
throw new Error("Error processing command", { cause: parsedArgs.error })
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// console.log(parsedArgs)
|
|
49
|
+
|
|
50
|
+
console.log("Zipping bundle...");
|
|
51
|
+
|
|
52
|
+
// Define a custome extension so we can still include zip files (in case user project has any in)
|
|
53
|
+
const bundleFileExtension = '.ELBZIP';
|
|
54
|
+
const bundleFileName = [new Date().getTime(), crypto.randomBytes(16).toString('hex'), bundleFileExtension].join('_');
|
|
55
|
+
const outputBundlePath = path.resolve(
|
|
56
|
+
process.cwd(),
|
|
57
|
+
bundleFileName
|
|
58
|
+
);
|
|
59
|
+
const outputBundleStream = fs.createWriteStream(outputBundlePath);
|
|
60
|
+
const archive = archiver('zip', { zlib: { level: 9 } })
|
|
61
|
+
|
|
62
|
+
// Catch warnings
|
|
63
|
+
archive.on("warning", (err) => {
|
|
64
|
+
if (err.code === 'ENOENT') {
|
|
65
|
+
console.warn(err)
|
|
66
|
+
} else {
|
|
67
|
+
throw err;
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// Handle errors
|
|
72
|
+
archive.on("error", (err) => {
|
|
73
|
+
throw err;
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// Pipe archive to file
|
|
77
|
+
archive.pipe(outputBundleStream);
|
|
78
|
+
|
|
79
|
+
const directories = (await fsPromises.readdir(process.cwd(), { withFileTypes: true }))
|
|
80
|
+
.filter(ent => ent.isDirectory())
|
|
81
|
+
.map(ent => ent.name)
|
|
82
|
+
.filter(ent => {
|
|
83
|
+
const ignoredEntries = [
|
|
84
|
+
'node_modules',
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
return !ignoredEntries.includes(ent)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
const rootDirFiles = (await fsPromises.readdir(process.cwd(), { withFileTypes: true }))
|
|
91
|
+
.filter(ent => ent.isFile())
|
|
92
|
+
.map(ent => ent.name)
|
|
93
|
+
.filter(ent => {
|
|
94
|
+
if (parsedArgs?.data?.config_file_path) {
|
|
95
|
+
const fileIsEnvConfigFile = path.basename(parsedArgs.data.config_file_path);
|
|
96
|
+
// Include the config file the user specified
|
|
97
|
+
if (ent === fileIsEnvConfigFile) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Exclude other .env files
|
|
103
|
+
if (ent.includes(".env")) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Don't include any files which use the same extension as we use for our bundle
|
|
108
|
+
if (ent.includes(bundleFileExtension)) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
// console.log(JSON.stringify({directories, rootDirFiles, outputBundlePath}, null, 2))
|
|
115
|
+
|
|
116
|
+
for (const file of rootDirFiles) {
|
|
117
|
+
const filePath = path.resolve(process.cwd(), file)
|
|
118
|
+
archive.append(fs.createReadStream(filePath), { name: file })
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (const dir of directories) {
|
|
122
|
+
const dirPath = path.resolve(process.cwd(), dir);
|
|
123
|
+
archive.directory(dirPath, dir)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
await archive.finalize()
|
|
127
|
+
|
|
128
|
+
outputBundleStream.on('close', async () => {
|
|
129
|
+
console.log("Bundle close!")
|
|
130
|
+
|
|
131
|
+
const formData = new FormData()
|
|
132
|
+
formData.append("bundle", fs.createReadStream(outputBundlePath))
|
|
133
|
+
formData.append("eas_profile", parsedArgs.data.profile);
|
|
134
|
+
formData.append("eas_platform", parsedArgs.data.platform);
|
|
135
|
+
formData.append("eas_access_token", parsedArgs.data.access_token);
|
|
136
|
+
formData.append("installer", parsedArgs.data.installer);
|
|
137
|
+
|
|
138
|
+
const request = await fetch(`${parsedArgs.data.build_server}/ingress`, {
|
|
139
|
+
method: 'POST',
|
|
140
|
+
body: formData,
|
|
141
|
+
// Note: node-fetch handles the headers automatically when using FormData
|
|
142
|
+
// But you might need to disable SSL verification if needed:
|
|
143
|
+
// agent: new (require('https').Agent)({ rejectUnauthorized: false })
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const response = await request.json()
|
|
147
|
+
|
|
148
|
+
console.log(JSON.stringify(response, null, 2))
|
|
149
|
+
fs.rmSync(outputBundlePath)
|
|
150
|
+
|
|
151
|
+
// formData.append('bundle', {
|
|
152
|
+
// [Symbol.toStringTag]: 'file',
|
|
153
|
+
// name: bundleFileName,
|
|
154
|
+
// stream: () => fs.createReadStream(outputBundlePath)
|
|
155
|
+
// })
|
|
156
|
+
|
|
157
|
+
// formData.append('bundle', fileAsBlob, bundleFileName);
|
|
158
|
+
|
|
159
|
+
// formData.append("eas_profile", parsedArgs.data.profile);
|
|
160
|
+
// formData.append("eas_platform", parsedArgs.data.platform);
|
|
161
|
+
// formData.append("eas_access_token", parsedArgs.data.access_token);
|
|
162
|
+
// const url = [parsedArgs.data.build_server, 'ingress'].join('/');
|
|
163
|
+
// const options = {
|
|
164
|
+
// method: 'POST',
|
|
165
|
+
// headers: {
|
|
166
|
+
// 'Content-Type': 'multipart/form-data; boundary=---bundle'
|
|
167
|
+
// },
|
|
168
|
+
// body: formData
|
|
169
|
+
// }
|
|
170
|
+
// const request = await fetch(url, options)
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
outputBundleStream.on('end', () => {
|
|
174
|
+
console.log("Bundle end!")
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// const fileAsBlob = await fs.openAsBlob(outputBundlePath);
|
|
178
|
+
// console.log(fileAsBlob);
|
|
179
|
+
|
|
180
|
+
// const formData = new FormData()
|
|
181
|
+
// formData.append("bundle", fs.createReadStream(outputBundlePath))
|
|
182
|
+
|
|
183
|
+
// // formData.append('bundle', {
|
|
184
|
+
// // [Symbol.toStringTag]: 'file',
|
|
185
|
+
// // name: bundleFileName,
|
|
186
|
+
// // stream: () => fs.createReadStream(outputBundlePath)
|
|
187
|
+
// // })
|
|
188
|
+
|
|
189
|
+
// // formData.append('bundle', fileAsBlob, bundleFileName);
|
|
190
|
+
|
|
191
|
+
// formData.append("eas_profile", parsedArgs.data.profile);
|
|
192
|
+
// formData.append("eas_platform", parsedArgs.data.platform);
|
|
193
|
+
// formData.append("eas_access_token", parsedArgs.data.access_token);
|
|
194
|
+
// const url = [parsedArgs.data.build_server, 'ingress'].join('/');
|
|
195
|
+
// const options = {
|
|
196
|
+
// method: 'POST',
|
|
197
|
+
// headers: {
|
|
198
|
+
// 'Content-Type': 'multipart/form-data; boundary=---bundle'
|
|
199
|
+
// },
|
|
200
|
+
// body: formData
|
|
201
|
+
// }
|
|
202
|
+
// const request = await fetch(url, options)
|
|
203
|
+
// fs.rmSync(outputBundlePath)
|
|
204
|
+
|
|
205
|
+
}
|