distapp 1.0.0 → 1.0.2
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/cli.mjs +506 -526
- package/package.json +4 -1
- package/cli.sh +0 -12
- package/cli.ts +0 -74
- package/extract-aab-to-apk.ts +0 -94
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "distapp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Manage and distribute Android or iOS app",
|
|
5
5
|
"main": "cli.mjs",
|
|
6
6
|
"bin": {
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node cli.mjs"
|
|
11
11
|
},
|
|
12
|
+
"files": [
|
|
13
|
+
"cli.mjs"
|
|
14
|
+
],
|
|
12
15
|
"author": "Yunus Efendi",
|
|
13
16
|
"license": "GPL-3.0-only",
|
|
14
17
|
"keywords": [
|
package/cli.sh
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env sh
|
|
2
|
-
if ! [ -x "$(command -v node)" ]; then
|
|
3
|
-
echo 'Error: node is not installed.' >&2
|
|
4
|
-
exit 1
|
|
5
|
-
fi
|
|
6
|
-
|
|
7
|
-
set -e
|
|
8
|
-
|
|
9
|
-
scriptUrl="https://github.com/yunusefendi52/distapp/raw/refs/heads/main/cli/cli.mjs"
|
|
10
|
-
scriptPath="/tmp/distapp-cli.mjs"
|
|
11
|
-
curl -sL -o $scriptPath -H 'Cache-Control: no-cache' "$scriptUrl"
|
|
12
|
-
DISTAPP_CLI_URL="https://distapp.lhf.my.id" node $scriptPath "$@"
|
package/cli.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { uploadArtifact, updateMyFetchApiKey } from '../utils/upload-utils.js'
|
|
4
|
-
import { promises } from "node:fs"
|
|
5
|
-
import { resolve } from "node:path"
|
|
6
|
-
import { parseArgs } from "node:util"
|
|
7
|
-
import { extractAabToApk } from './extract-aab-to-apk.js'
|
|
8
|
-
import { basename, extname } from 'path'
|
|
9
|
-
|
|
10
|
-
const args = parseArgs({
|
|
11
|
-
options: {
|
|
12
|
-
distribute: {
|
|
13
|
-
type: 'boolean',
|
|
14
|
-
},
|
|
15
|
-
slug: {
|
|
16
|
-
type: 'string',
|
|
17
|
-
},
|
|
18
|
-
file: {
|
|
19
|
-
type: 'string',
|
|
20
|
-
},
|
|
21
|
-
releaseNotes: {
|
|
22
|
-
type: 'string',
|
|
23
|
-
},
|
|
24
|
-
apiKey: {
|
|
25
|
-
type: 'string',
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
const { values } = args
|
|
31
|
-
|
|
32
|
-
function slugToOrgApp(slug: string): { orgName: string, appName: string } {
|
|
33
|
-
const slugPath = slug.split('/')
|
|
34
|
-
return {
|
|
35
|
-
orgName: slugPath[0],
|
|
36
|
-
appName: slugPath[1],
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async function start() {
|
|
41
|
-
if (!values.apiKey) {
|
|
42
|
-
console.error('API Key required')
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
updateMyFetchApiKey(values.apiKey)
|
|
46
|
-
if (values.distribute) {
|
|
47
|
-
const { orgName, appName } = slugToOrgApp(values.slug!)
|
|
48
|
-
const filePath = resolve(values.file!)
|
|
49
|
-
const filename = basename(filePath, extname(filePath))
|
|
50
|
-
const file = await promises.readFile(filePath)
|
|
51
|
-
console.log("Distributing", {
|
|
52
|
-
filePath,
|
|
53
|
-
})
|
|
54
|
-
var bundleApkPath: string | undefined = undefined
|
|
55
|
-
var disposeBundle: (() => Promise<void>) | undefined
|
|
56
|
-
try {
|
|
57
|
-
if (filePath.endsWith('.aab')) {
|
|
58
|
-
const aabPath = filePath
|
|
59
|
-
const { bundleApk, dispose } = await extractAabToApk(aabPath)
|
|
60
|
-
bundleApkPath = bundleApk
|
|
61
|
-
disposeBundle = dispose
|
|
62
|
-
}
|
|
63
|
-
const bundleApkFile = bundleApkPath ? await promises.readFile(bundleApkPath) : undefined
|
|
64
|
-
await uploadArtifact(file, filename, orgName, appName, values.releaseNotes ? values.releaseNotes : null, bundleApkFile)
|
|
65
|
-
console.log(`Finished Distributing "${filePath}"` + (bundleApkPath ? ' with generated APK' : ''))
|
|
66
|
-
} finally {
|
|
67
|
-
await disposeBundle?.()
|
|
68
|
-
}
|
|
69
|
-
} else {
|
|
70
|
-
console.error('No valid command')
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
start()
|
package/extract-aab-to-apk.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import util from 'util'
|
|
2
|
-
import { join, basename, extname } from 'path'
|
|
3
|
-
import { promises, existsSync } from 'fs'
|
|
4
|
-
import child_process from 'node:child_process'
|
|
5
|
-
import { uuidv4 } from "uuidv7"
|
|
6
|
-
const exec = util.promisify(child_process.exec)
|
|
7
|
-
import { myFetch } from '../utils/upload-utils.js'
|
|
8
|
-
import type { BundleKeystoreResponse } from '../server/api/artifacts/get-bundle-keystore.get.js'
|
|
9
|
-
import { downloadFile } from '~/server/services/downloadFile.js'
|
|
10
|
-
|
|
11
|
-
function getDateFilename(): string {
|
|
12
|
-
const today = new Date()
|
|
13
|
-
const dd = String(today.getDate()).padStart(2, '0')
|
|
14
|
-
const mm = String(today.getMonth() + 1).padStart(2, '0')
|
|
15
|
-
const yyyy = today.getFullYear()
|
|
16
|
-
|
|
17
|
-
return `${yyyy}_${mm}_${dd}_${today.getHours()}_${today.getMinutes()}`
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async function getBundleKeystore(keystoreFile: string) {
|
|
21
|
-
const bundleKeystoreResponse: BundleKeystoreResponse | undefined = await myFetch('/api/artifacts/get-bundle-keystore')
|
|
22
|
-
if (!bundleKeystoreResponse) {
|
|
23
|
-
throw 'Error bundleKeystoreResponse'
|
|
24
|
-
}
|
|
25
|
-
var keystoreUrl = bundleKeystoreResponse.appKeystoreUrl
|
|
26
|
-
if (keystoreUrl.startsWith('/')) {
|
|
27
|
-
keystoreUrl = `${process.env.DISTAPP_CLI_URL}${keystoreUrl}`
|
|
28
|
-
}
|
|
29
|
-
await downloadFile(keystoreUrl, keystoreFile)
|
|
30
|
-
return bundleKeystoreResponse
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function getBundletoolPath(bundeFilesDir: string): Promise<string> {
|
|
34
|
-
if (process.env.DISTAPP_BUNDLETOOL_PATH) {
|
|
35
|
-
return process.env.DISTAPP_BUNDLETOOL_PATH
|
|
36
|
-
} else {
|
|
37
|
-
const bundletoolJarPath = join(bundeFilesDir, 'bundletool.jar')
|
|
38
|
-
const bundletoolCheck = await exec(`java -jar "${bundletoolJarPath}" version || echo "Error check bundletool version"`)
|
|
39
|
-
if (!bundletoolCheck.stdout.includes('1.17.2')) {
|
|
40
|
-
await downloadFile('https://github.com/google/bundletool/releases/download/1.17.2/bundletool-all-1.17.2.jar', bundletoolJarPath)
|
|
41
|
-
}
|
|
42
|
-
return bundletoolJarPath
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export async function extractAabToApk(aabPath: string, bundleKeystoreFetcher?: (keystoreFile: string) => Promise<BundleKeystoreResponse>) {
|
|
47
|
-
const cwdRoot = process.cwd()
|
|
48
|
-
const bundeFilesDir = join(cwdRoot, '.distapp-data', 'bundle_files')
|
|
49
|
-
await promises.mkdir(bundeFilesDir, {
|
|
50
|
-
recursive: true,
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
const bundletoolJarPath = await getBundletoolPath(bundeFilesDir)
|
|
54
|
-
|
|
55
|
-
const tempBundleDir = join(bundeFilesDir, `${getDateFilename()}_${uuidv4().replaceAll('-', '').slice(0, 12)}`)
|
|
56
|
-
// console.log('extract_aab: ', {
|
|
57
|
-
// tempBundleDir: tempBundleDir,
|
|
58
|
-
// })
|
|
59
|
-
await promises.mkdir(tempBundleDir, {
|
|
60
|
-
recursive: true,
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
const bundleApks = join(tempBundleDir, "bundle.apks")
|
|
64
|
-
const actualApk = join(tempBundleDir, `${basename(aabPath, extname(aabPath))}.apk`)
|
|
65
|
-
const keystoreFile = join(tempBundleDir, `app.jks`)
|
|
66
|
-
|
|
67
|
-
const bundleKeystore = bundleKeystoreFetcher
|
|
68
|
-
? await bundleKeystoreFetcher?.(keystoreFile)
|
|
69
|
-
: await getBundleKeystore(keystoreFile)
|
|
70
|
-
|
|
71
|
-
await exec(`
|
|
72
|
-
java -jar "${bundletoolJarPath}" build-apks --bundle=${aabPath} --output=${bundleApks} --mode=universal \\
|
|
73
|
-
--ks="${keystoreFile}" \\
|
|
74
|
-
--ks-pass=pass:${bundleKeystore.appKeystorePass} \\
|
|
75
|
-
--ks-key-alias=${bundleKeystore.appKeystoreAlias} \\
|
|
76
|
-
--key-pass=pass:${bundleKeystore.appKeystorePass}
|
|
77
|
-
`)
|
|
78
|
-
await exec(`unzip -p "${bundleApks}" universal.apk > ${actualApk}`)
|
|
79
|
-
await promises.rm(bundleApks, {
|
|
80
|
-
force: true,
|
|
81
|
-
})
|
|
82
|
-
// console.log('extract_aab: success', {
|
|
83
|
-
// output: actualApk,
|
|
84
|
-
// })
|
|
85
|
-
return {
|
|
86
|
-
bundleApk: actualApk,
|
|
87
|
-
dispose: async () => {
|
|
88
|
-
await promises.rm(tempBundleDir, {
|
|
89
|
-
force: true,
|
|
90
|
-
recursive: true,
|
|
91
|
-
})
|
|
92
|
-
},
|
|
93
|
-
}
|
|
94
|
-
}
|