pakstr 0.18.1 → 0.18.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/README.md +61 -15
- package/dist/android/icon.js +27 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,33 +1,79 @@
|
|
|
1
1
|
# Pakstr
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Pakstr** turns your web app into a signed, installable Android APK — and publishes it to **Zap Store** — in one CI step, with one secret.
|
|
4
|
+
|
|
5
|
+
Pakstr takes a folder of built web assets (a `dist/` containing an `index.html`) and produces a signed Android APK. You bring one secret — a Nostr `nsec` — and run one command: `pakstr run`. **No Android SDK, no Gradle, no Java, and no keystores to manage locally.**
|
|
6
|
+
|
|
7
|
+
The same `nsec` serves two core purposes:
|
|
8
|
+
1. **Deterministically derives the APK signing key** – the same `nsec` + app ID always produces the same signature, allowing seamless application updates across releases.
|
|
9
|
+
2. **Authenticates the Zap Store publish** – handles the authorization needed to publish your app to the store.
|
|
10
|
+
|
|
11
|
+
---
|
|
4
12
|
|
|
5
13
|
## Status
|
|
6
14
|
|
|
7
|
-
Pakstr is currently in early development (0.x)
|
|
15
|
+
Pakstr is currently in **early development (0.x)**.
|
|
16
|
+
The CLI API and configuration format may change before 1.0.0.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
* **Node.js** 22+
|
|
23
|
+
* **Docker Desktop**
|
|
24
|
+
|
|
25
|
+
*Note: No Android SDK, Gradle, Java, or Android keystore setup is required locally.*
|
|
8
26
|
|
|
9
|
-
|
|
27
|
+
---
|
|
10
28
|
|
|
11
|
-
##
|
|
29
|
+
## Quick Start
|
|
12
30
|
|
|
31
|
+
Run the following commands from your web app project root:
|
|
32
|
+
|
|
33
|
+
### 1. Initialize the project
|
|
13
34
|
```bash
|
|
14
|
-
|
|
35
|
+
npx pakstr init
|
|
15
36
|
```
|
|
37
|
+
This creates `pakstr.yaml`, `zapstore.yaml`, and a `.env` file (automatically added to `.gitignore`) containing your `PAKSTR_NSEC`.
|
|
38
|
+
|
|
39
|
+
### 2. Configure your web assets
|
|
40
|
+
Adjust the paths inside the generated `pakstr.yaml` file:
|
|
16
41
|
|
|
17
|
-
|
|
42
|
+
```yaml
|
|
43
|
+
build:
|
|
44
|
+
web: ./dist
|
|
45
|
+
out: ./build/app.apk
|
|
46
|
+
builder: docker
|
|
47
|
+
```
|
|
18
48
|
|
|
49
|
+
### 3. Build, sign, and publish
|
|
19
50
|
```bash
|
|
20
|
-
pakstr
|
|
21
|
-
--manifest app.manifest.json \
|
|
22
|
-
--web ./dist \
|
|
23
|
-
--out ./build/app.apk
|
|
51
|
+
npx pakstr run
|
|
24
52
|
```
|
|
25
53
|
|
|
26
|
-
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Commands
|
|
57
|
+
|
|
58
|
+
* `npx pakstr init` — Initialize a Pakstr project.
|
|
59
|
+
* `npx pakstr sign` — Sign the APK using the key derived from your `nsec`.
|
|
60
|
+
* `npx pakstr publish` — Publish the signed APK to Zap Store.
|
|
61
|
+
* `npx pakstr run` — Execute the full pipeline at once (**build** + **sign** + **publish**).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## CI/CD
|
|
66
|
+
|
|
67
|
+
Set `PAKSTR_NSEC` as a CI secret in your repository provider (e.g., GitHub Actions) and run:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm run build
|
|
71
|
+
npx pakstr run
|
|
72
|
+
```
|
|
27
73
|
|
|
28
|
-
|
|
29
|
-
- Docker Desktop (for Docker builds)
|
|
74
|
+
---
|
|
30
75
|
|
|
31
|
-
## License
|
|
76
|
+
## Documentation & License
|
|
32
77
|
|
|
33
|
-
|
|
78
|
+
* See `docs/SPEC.md` for the full configuration and signing specification.
|
|
79
|
+
* License: **MIT**
|
package/dist/android/icon.js
CHANGED
|
@@ -51,28 +51,43 @@ async function patchIcon(androidRoot, iconPath, backgroundColor = "#FFFFFF", man
|
|
|
51
51
|
// 2. ADAPTIVE FOREGROUND
|
|
52
52
|
//
|
|
53
53
|
const drawablePath = path_1.default.join(resPath, "drawable");
|
|
54
|
+
const adaptiveDrawablePath = path_1.default.join(resPath, "drawable-xxxhdpi");
|
|
55
|
+
const transparent = {
|
|
56
|
+
r: 0,
|
|
57
|
+
g: 0,
|
|
58
|
+
b: 0,
|
|
59
|
+
alpha: 0,
|
|
60
|
+
};
|
|
54
61
|
fs_1.default.mkdirSync(drawablePath, {
|
|
55
62
|
recursive: true,
|
|
56
63
|
});
|
|
64
|
+
fs_1.default.mkdirSync(adaptiveDrawablePath, {
|
|
65
|
+
recursive: true,
|
|
66
|
+
});
|
|
57
67
|
await (0, sharp_1.default)(absoluteIconPath)
|
|
58
|
-
.
|
|
68
|
+
.trim({ background: transparent, threshold: 0 })
|
|
69
|
+
.resize(264, 264, {
|
|
59
70
|
fit: "contain",
|
|
60
|
-
background:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
background: transparent,
|
|
72
|
+
})
|
|
73
|
+
.extend({
|
|
74
|
+
top: 84,
|
|
75
|
+
bottom: 84,
|
|
76
|
+
left: 84,
|
|
77
|
+
right: 84,
|
|
78
|
+
background: transparent,
|
|
66
79
|
})
|
|
67
80
|
.webp()
|
|
68
|
-
.toFile(path_1.default.join(
|
|
81
|
+
.toFile(path_1.default.join(adaptiveDrawablePath, "ic_launcher_foreground.webp"));
|
|
69
82
|
console.log("🖼️ Generated adaptive foreground");
|
|
70
83
|
//
|
|
71
|
-
// 3. REMOVE OLD
|
|
84
|
+
// 3. REMOVE OLD UNQUALIFIED FOREGROUNDS
|
|
72
85
|
//
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
fs_1.default.
|
|
86
|
+
for (const file of ["ic_launcher_foreground.xml", "ic_launcher_foreground.webp"]) {
|
|
87
|
+
const oldForeground = path_1.default.join(drawablePath, file);
|
|
88
|
+
if (fs_1.default.existsSync(oldForeground)) {
|
|
89
|
+
fs_1.default.unlinkSync(oldForeground);
|
|
90
|
+
}
|
|
76
91
|
}
|
|
77
92
|
//
|
|
78
93
|
// 4. BACKGROUND COLOR
|