pakstr 0.9.0 → 0.10.0
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/dist/commands/init.js +53 -6
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -23,7 +23,7 @@ const HEADER = `# pakstr.yaml — one file, one command, one APK.
|
|
|
23
23
|
# has it can derive every app identity for every known appId. Losing it breaks
|
|
24
24
|
# update continuity. It cannot rotate the signer of an already-published app.
|
|
25
25
|
`;
|
|
26
|
-
function initCommand(options = {}) {
|
|
26
|
+
async function initCommand(options = {}) {
|
|
27
27
|
const configPath = path_1.default.resolve(options.out ?? path_1.default.join(process.cwd(), pakstrConfig_1.PAKSTR_CONFIG_FILENAME));
|
|
28
28
|
if (fs_1.default.existsSync(configPath) && !options.force) {
|
|
29
29
|
throw new Error(`${configPath} already exists. Use --force to overwrite, or remove it first.`);
|
|
@@ -53,8 +53,11 @@ function initCommand(options = {}) {
|
|
|
53
53
|
}
|
|
54
54
|
// Generate a fresh dev nsec into a gitignored `.env` so `pakstr run` works
|
|
55
55
|
// locally with no manual setup. Never overwrites an existing PAKSTR_NSEC.
|
|
56
|
-
const nsecStatus = ensureDevNsec();
|
|
56
|
+
const { nsec: devNsec, status: nsecStatus } = ensureDevNsec();
|
|
57
57
|
ensureGitIgnoresEnv();
|
|
58
|
+
// Write zapstore.yaml (relay-side publisher whitelist) with the publisher
|
|
59
|
+
// npub derived from the dev nsec. Never overwrites an existing one.
|
|
60
|
+
const zapstoreStatus = await ensureZapstoreYaml(devNsec);
|
|
58
61
|
console.log("");
|
|
59
62
|
console.log("➡️ Next: run pakstr run");
|
|
60
63
|
if (nsecStatus === "generated") {
|
|
@@ -63,27 +66,35 @@ function initCommand(options = {}) {
|
|
|
63
66
|
else if (nsecStatus === "present") {
|
|
64
67
|
console.log(` ${nostr_1.PAKSTR_NSEC_ENV} already in .env — left untouched.`);
|
|
65
68
|
}
|
|
69
|
+
if (zapstoreStatus === "generated") {
|
|
70
|
+
console.log(" zapstore.yaml written (relay-side publisher whitelist). Commit it.");
|
|
71
|
+
}
|
|
72
|
+
else if (zapstoreStatus === "present") {
|
|
73
|
+
console.log(" zapstore.yaml already exists — left untouched.");
|
|
74
|
+
}
|
|
66
75
|
console.log("");
|
|
67
76
|
console.log(` For real releases, put the SAME ${nostr_1.PAKSTR_NSEC_ENV} in your CI secret manager`);
|
|
68
77
|
console.log(" (reusing it is what lets an update install over the previous APK).");
|
|
69
78
|
console.log(` ${nostr_1.PAKSTR_NSEC_ENV} is a release-signing root secret: anyone who has it can`);
|
|
70
79
|
console.log(" sign updates for every app whose appId they know. Keep it safe.");
|
|
71
80
|
}
|
|
72
|
-
/** Generate a dev nsec into .env if none is present there. Returns
|
|
81
|
+
/** Generate a dev nsec into .env if none is present there. Returns the nsec string. */
|
|
73
82
|
function ensureDevNsec() {
|
|
74
83
|
const envPath = path_1.default.join(process.cwd(), ".env");
|
|
75
84
|
const existing = fs_1.default.existsSync(envPath)
|
|
76
85
|
? fs_1.default.readFileSync(envPath, "utf8")
|
|
77
86
|
: "";
|
|
78
|
-
if (containsPakstrNsec(existing))
|
|
79
|
-
|
|
87
|
+
if (containsPakstrNsec(existing)) {
|
|
88
|
+
const m = existing.match(new RegExp(`^${nostr_1.PAKSTR_NSEC_ENV}=(\\S+)`, "m"));
|
|
89
|
+
return { nsec: m?.[1] ?? "", status: "present" };
|
|
90
|
+
}
|
|
80
91
|
const nsec = (0, nostr_1.encodeNsec)((0, crypto_1.randomBytes)(32));
|
|
81
92
|
const line = `${nostr_1.PAKSTR_NSEC_ENV}=${nsec}\n`;
|
|
82
93
|
const header = existing.length === 0 ? "# Local development secrets — never commit this file.\n" : "";
|
|
83
94
|
fs_1.default.writeFileSync(envPath, header + (existing.length ? "\n" + line : line), {
|
|
84
95
|
flag: existing.length === 0 ? "wx" : "a",
|
|
85
96
|
});
|
|
86
|
-
return "generated";
|
|
97
|
+
return { nsec, status: "generated" };
|
|
87
98
|
}
|
|
88
99
|
function containsPakstrNsec(envText) {
|
|
89
100
|
return new RegExp(`^${nostr_1.PAKSTR_NSEC_ENV}=`, "m").test(envText);
|
|
@@ -108,6 +119,42 @@ function containsEnvEntry(gitignoreText) {
|
|
|
108
119
|
.split(/\r?\n/)
|
|
109
120
|
.some(line => line.trim() === ".env" || line.trim().startsWith(".env"));
|
|
110
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Write `zapstore.yaml` (relay-side publisher whitelist) with the publisher
|
|
124
|
+
* npub derived from the dev nsec. Never overwrites an existing file.
|
|
125
|
+
* Returns what happened.
|
|
126
|
+
*/
|
|
127
|
+
async function ensureZapstoreYaml(devNsec) {
|
|
128
|
+
const zapstorePath = path_1.default.join(process.cwd(), "zapstore.yaml");
|
|
129
|
+
if (fs_1.default.existsSync(zapstorePath))
|
|
130
|
+
return "present";
|
|
131
|
+
let npub = "";
|
|
132
|
+
if (devNsec) {
|
|
133
|
+
try {
|
|
134
|
+
const secret = (0, nostr_1.decodeNsec)(devNsec);
|
|
135
|
+
const hex = await (0, nostr_1.getNpubHex)(secret);
|
|
136
|
+
npub = (0, nostr_1.pubkeyHexToNpub)(hex);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// If we can't derive the npub, write the file with a placeholder so the
|
|
140
|
+
// user knows to fill it in.
|
|
141
|
+
npub = "";
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const content = `# zapstore.yaml — relay-side publisher whitelist (NIP-82 / Zap Store).
|
|
145
|
+
# The relay fetches this file from your repo to verify the publisher's pubkey
|
|
146
|
+
# is authorized for this repository. Generated by \`pakstr init\`.
|
|
147
|
+
#
|
|
148
|
+
# \`pubkey\` is the npub matching the nsec used to publish (PAKSTR_NSEC, or
|
|
149
|
+
# PAKSTR_PUBLISH_NSEC if you set publish.publishKey). Replace it with your
|
|
150
|
+
# real publisher npub for production releases if different from your dev nsec.
|
|
151
|
+
|
|
152
|
+
repository: # TODO: set to your app's source code repository URL
|
|
153
|
+
pubkey: ${npub || "# TODO: set to your publisher npub (npub1...)"}
|
|
154
|
+
`;
|
|
155
|
+
fs_1.default.writeFileSync(zapstorePath, content, "utf8");
|
|
156
|
+
return "generated";
|
|
157
|
+
}
|
|
111
158
|
function renderConfig(c) {
|
|
112
159
|
const perms = ` [${pakstrConfig_1.PERMISSION_ALIASES.map(p => `"${p}"`).join(", ")}]`;
|
|
113
160
|
return `${HEADER}
|