@sitepong/fastnode 0.1.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/README.md +81 -0
- package/bin/fastnode.js +13 -0
- package/bin/fastnode.ts +5 -0
- package/dist/actions/index.cjs +7405 -0
- package/dist/actions/index.cjs.map +1 -0
- package/dist/actions/index.d.cts +15 -0
- package/dist/actions/index.d.ts +15 -0
- package/dist/actions/index.mjs +7377 -0
- package/dist/actions/index.mjs.map +1 -0
- package/dist/cert/index.cjs +219 -0
- package/dist/cert/index.cjs.map +1 -0
- package/dist/cert/index.d.cts +4 -0
- package/dist/cert/index.d.ts +4 -0
- package/dist/cert/index.mjs +191 -0
- package/dist/cert/index.mjs.map +1 -0
- package/dist/cert-BmJGtYtb.d.cts +27 -0
- package/dist/cert-owkOFNW8.d.ts +27 -0
- package/dist/cli/index.cjs +7998 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +9 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.mjs +7972 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/client/index.cjs +2592 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +2 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.mjs +2582 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/context-CymLkfrS.d.cts +13 -0
- package/dist/context-CymLkfrS.d.ts +13 -0
- package/dist/core/index.cjs +281 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.mjs +254 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/deliver/index.cjs +328 -0
- package/dist/deliver/index.cjs.map +1 -0
- package/dist/deliver/index.d.cts +3 -0
- package/dist/deliver/index.d.ts +3 -0
- package/dist/deliver/index.mjs +322 -0
- package/dist/deliver/index.mjs.map +1 -0
- package/dist/enums-B609j2rb.d.cts +20 -0
- package/dist/enums-B609j2rb.d.ts +20 -0
- package/dist/frameit/index.cjs +247 -0
- package/dist/frameit/index.cjs.map +1 -0
- package/dist/frameit/index.d.cts +1 -0
- package/dist/frameit/index.d.ts +1 -0
- package/dist/frameit/index.mjs +242 -0
- package/dist/frameit/index.mjs.map +1 -0
- package/dist/gym/index.cjs +356 -0
- package/dist/gym/index.cjs.map +1 -0
- package/dist/gym/index.d.cts +2 -0
- package/dist/gym/index.d.ts +2 -0
- package/dist/gym/index.mjs +346 -0
- package/dist/gym/index.mjs.map +1 -0
- package/dist/index-1Vu2cRQ2.d.ts +99 -0
- package/dist/index-A5MimeQk.d.ts +72 -0
- package/dist/index-B0yhu_LZ.d.ts +76 -0
- package/dist/index-B9yXicrQ.d.ts +62 -0
- package/dist/index-BFdNOmPJ.d.cts +53 -0
- package/dist/index-BLubSlgK.d.cts +1513 -0
- package/dist/index-BN0ubxjZ.d.ts +70 -0
- package/dist/index-BQJIJlK7.d.cts +70 -0
- package/dist/index-BYonklf3.d.cts +84 -0
- package/dist/index-BYonklf3.d.ts +84 -0
- package/dist/index-BimqCmY8.d.cts +78 -0
- package/dist/index-BimqCmY8.d.ts +78 -0
- package/dist/index-BoU8qt8r.d.cts +59 -0
- package/dist/index-BoU8qt8r.d.ts +59 -0
- package/dist/index-C2yG3wXA.d.cts +95 -0
- package/dist/index-C2yG3wXA.d.ts +95 -0
- package/dist/index-CR3BFPIz.d.cts +77 -0
- package/dist/index-CR3BFPIz.d.ts +77 -0
- package/dist/index-CWNLnSOL.d.cts +99 -0
- package/dist/index-Cp6cjtd-.d.cts +65 -0
- package/dist/index-Cp6cjtd-.d.ts +65 -0
- package/dist/index-D1Izm7qt.d.ts +1513 -0
- package/dist/index-D5eihzwM.d.cts +76 -0
- package/dist/index-DImN9PWc.d.ts +155 -0
- package/dist/index-DfCUVJX1.d.cts +62 -0
- package/dist/index-DfirmFbC.d.ts +32 -0
- package/dist/index-DkvinY7_.d.ts +54 -0
- package/dist/index-DrUpRXRG.d.cts +155 -0
- package/dist/index-EcVvViW8.d.cts +72 -0
- package/dist/index-HRiaaX-Q.d.cts +54 -0
- package/dist/index-TfXqwuac.d.ts +53 -0
- package/dist/index-lt819Jgj.d.cts +32 -0
- package/dist/index.cjs +8464 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.mjs +8410 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lane/index.cjs +7641 -0
- package/dist/lane/index.cjs.map +1 -0
- package/dist/lane/index.d.cts +51 -0
- package/dist/lane/index.d.ts +51 -0
- package/dist/lane/index.mjs +7603 -0
- package/dist/lane/index.mjs.map +1 -0
- package/dist/match/index.cjs +942 -0
- package/dist/match/index.cjs.map +1 -0
- package/dist/match/index.d.cts +5 -0
- package/dist/match/index.d.ts +5 -0
- package/dist/match/index.mjs +913 -0
- package/dist/match/index.mjs.map +1 -0
- package/dist/pem/index.cjs +195 -0
- package/dist/pem/index.cjs.map +1 -0
- package/dist/pem/index.d.cts +3 -0
- package/dist/pem/index.d.ts +3 -0
- package/dist/pem/index.mjs +170 -0
- package/dist/pem/index.mjs.map +1 -0
- package/dist/pilot/index.cjs +206 -0
- package/dist/pilot/index.cjs.map +1 -0
- package/dist/pilot/index.d.cts +3 -0
- package/dist/pilot/index.d.ts +3 -0
- package/dist/pilot/index.mjs +196 -0
- package/dist/pilot/index.mjs.map +1 -0
- package/dist/precheck/index.cjs +277 -0
- package/dist/precheck/index.cjs.map +1 -0
- package/dist/precheck/index.d.cts +3 -0
- package/dist/precheck/index.d.ts +3 -0
- package/dist/precheck/index.mjs +274 -0
- package/dist/precheck/index.mjs.map +1 -0
- package/dist/produce/index.cjs +200 -0
- package/dist/produce/index.cjs.map +1 -0
- package/dist/produce/index.d.cts +3 -0
- package/dist/produce/index.d.ts +3 -0
- package/dist/produce/index.mjs +191 -0
- package/dist/produce/index.mjs.map +1 -0
- package/dist/scan/index.cjs +187 -0
- package/dist/scan/index.cjs.map +1 -0
- package/dist/scan/index.d.cts +1 -0
- package/dist/scan/index.d.ts +1 -0
- package/dist/scan/index.mjs +183 -0
- package/dist/scan/index.mjs.map +1 -0
- package/dist/sigh/index.cjs +203 -0
- package/dist/sigh/index.cjs.map +1 -0
- package/dist/sigh/index.d.cts +3 -0
- package/dist/sigh/index.d.ts +3 -0
- package/dist/sigh/index.mjs +198 -0
- package/dist/sigh/index.mjs.map +1 -0
- package/dist/snapshot/index.cjs +448 -0
- package/dist/snapshot/index.cjs.map +1 -0
- package/dist/snapshot/index.d.cts +1 -0
- package/dist/snapshot/index.d.ts +1 -0
- package/dist/snapshot/index.mjs +438 -0
- package/dist/snapshot/index.mjs.map +1 -0
- package/dist/trainer/index.cjs +395 -0
- package/dist/trainer/index.cjs.map +1 -0
- package/dist/trainer/index.d.cts +1 -0
- package/dist/trainer/index.d.ts +1 -0
- package/dist/trainer/index.mjs +372 -0
- package/dist/trainer/index.mjs.map +1 -0
- package/dist/xcode/index.cjs +188 -0
- package/dist/xcode/index.cjs.map +1 -0
- package/dist/xcode/index.d.cts +1 -0
- package/dist/xcode/index.d.ts +1 -0
- package/dist/xcode/index.mjs +176 -0
- package/dist/xcode/index.mjs.map +1 -0
- package/package.json +223 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var child_process = require('child_process');
|
|
4
|
+
var util = require('util');
|
|
5
|
+
var promises = require('fs/promises');
|
|
6
|
+
var path = require('path');
|
|
7
|
+
var x509 = require('@peculiar/x509');
|
|
8
|
+
var crypto = require('crypto');
|
|
9
|
+
var fs = require('fs');
|
|
10
|
+
var os = require('os');
|
|
11
|
+
|
|
12
|
+
function _interopNamespace(e) {
|
|
13
|
+
if (e && e.__esModule) return e;
|
|
14
|
+
var n = Object.create(null);
|
|
15
|
+
if (e) {
|
|
16
|
+
Object.keys(e).forEach(function (k) {
|
|
17
|
+
if (k !== 'default') {
|
|
18
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
19
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () { return e[k]; }
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
n.default = e;
|
|
27
|
+
return Object.freeze(n);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var x509__namespace = /*#__PURE__*/_interopNamespace(x509);
|
|
31
|
+
|
|
32
|
+
// src/cert/cert.ts
|
|
33
|
+
x509__namespace.cryptoProvider.set(crypto.webcrypto);
|
|
34
|
+
function toPem(header, der) {
|
|
35
|
+
const b64 = der.toString("base64");
|
|
36
|
+
const lines = [];
|
|
37
|
+
for (let i = 0; i < b64.length; i += 64) lines.push(b64.slice(i, i + 64));
|
|
38
|
+
return `-----BEGIN ${header}-----
|
|
39
|
+
${lines.join("\n")}
|
|
40
|
+
-----END ${header}-----`;
|
|
41
|
+
}
|
|
42
|
+
async function generateCSR() {
|
|
43
|
+
const algorithm = { name: "ECDSA", namedCurve: "P-256" };
|
|
44
|
+
const keyPair = await crypto.webcrypto.subtle.generateKey(algorithm, true, ["sign", "verify"]);
|
|
45
|
+
const csr = await x509__namespace.Pkcs10CertificateRequestGenerator.create({
|
|
46
|
+
name: "CN=PEM",
|
|
47
|
+
keys: keyPair,
|
|
48
|
+
signingAlgorithm: { name: "ECDSA", hash: "SHA-256" }
|
|
49
|
+
});
|
|
50
|
+
const pkcs8 = await crypto.webcrypto.subtle.exportKey("pkcs8", keyPair.privateKey);
|
|
51
|
+
return {
|
|
52
|
+
csr: csr.toString("pem"),
|
|
53
|
+
privateKey: toPem("PRIVATE KEY", Buffer.from(pkcs8))
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function generateRSACSR() {
|
|
57
|
+
const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
|
|
58
|
+
modulusLength: 2048,
|
|
59
|
+
privateKeyEncoding: { type: "pkcs8", format: "pem" },
|
|
60
|
+
publicKeyEncoding: { type: "spki", format: "pem" }
|
|
61
|
+
});
|
|
62
|
+
const keyPath = path.join(os.tmpdir(), `fastnode-rsa-${Date.now()}.pem`);
|
|
63
|
+
const csrPath = path.join(os.tmpdir(), `fastnode-rsa-${Date.now()}.csr`);
|
|
64
|
+
try {
|
|
65
|
+
fs.writeFileSync(keyPath, privateKey);
|
|
66
|
+
child_process.execSync(`openssl req -new -key "${keyPath}" -out "${csrPath}" -subj "/CN=PEM" 2>/dev/null`);
|
|
67
|
+
const csr = fs.readFileSync(csrPath, "utf-8");
|
|
68
|
+
return { csr, privateKey };
|
|
69
|
+
} finally {
|
|
70
|
+
try {
|
|
71
|
+
fs.unlinkSync(keyPath);
|
|
72
|
+
} catch {
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
fs.unlinkSync(csrPath);
|
|
76
|
+
} catch {
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/cert/cert.ts
|
|
82
|
+
var execFileAsync = util.promisify(child_process.execFile);
|
|
83
|
+
function resolveCertificateTypes(options) {
|
|
84
|
+
if (options.type) return [options.type];
|
|
85
|
+
const platform = options.platform ?? "ios";
|
|
86
|
+
if (options.development) {
|
|
87
|
+
return platform === "macos" ? ["MAC_APP_DEVELOPMENT"] : ["IOS_DEVELOPMENT"];
|
|
88
|
+
}
|
|
89
|
+
return platform === "macos" ? ["MAC_APP_DISTRIBUTION"] : ["IOS_DISTRIBUTION"];
|
|
90
|
+
}
|
|
91
|
+
async function findValidCertificates(options) {
|
|
92
|
+
const types = resolveCertificateTypes(options);
|
|
93
|
+
const certs = await options.client.certificates.list({
|
|
94
|
+
filter: { certificateType: types },
|
|
95
|
+
limit: 200
|
|
96
|
+
});
|
|
97
|
+
const now = /* @__PURE__ */ new Date();
|
|
98
|
+
return certs.filter(
|
|
99
|
+
(c) => new Date(c.attributes.expirationDate) > now
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
async function createCertificate(options) {
|
|
103
|
+
if (!options.force) {
|
|
104
|
+
const existing = await findValidCertificates(options);
|
|
105
|
+
if (existing.length > 0) {
|
|
106
|
+
const cert2 = existing[0];
|
|
107
|
+
const content2 = Buffer.from(cert2.attributes.certificateContent, "base64");
|
|
108
|
+
const result2 = {
|
|
109
|
+
certificate: cert2,
|
|
110
|
+
privateKey: "",
|
|
111
|
+
certificateContent: content2
|
|
112
|
+
};
|
|
113
|
+
if (options.outputDir) {
|
|
114
|
+
await promises.mkdir(options.outputDir, { recursive: true });
|
|
115
|
+
const certPath = path.join(options.outputDir, `${cert2.id}.cer`);
|
|
116
|
+
await promises.writeFile(certPath, content2);
|
|
117
|
+
result2.certPath = certPath;
|
|
118
|
+
}
|
|
119
|
+
return result2;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const types = resolveCertificateTypes(options);
|
|
123
|
+
const { csr, privateKey } = await generateCSR();
|
|
124
|
+
const cert = await options.client.certificates.create({
|
|
125
|
+
certificateType: types[0],
|
|
126
|
+
csrContent: csr
|
|
127
|
+
});
|
|
128
|
+
const content = Buffer.from(cert.attributes.certificateContent, "base64");
|
|
129
|
+
const result = {
|
|
130
|
+
certificate: cert,
|
|
131
|
+
privateKey,
|
|
132
|
+
certificateContent: content
|
|
133
|
+
};
|
|
134
|
+
if (options.outputDir) {
|
|
135
|
+
await promises.mkdir(options.outputDir, { recursive: true });
|
|
136
|
+
const certPath = path.join(options.outputDir, `${cert.id}.cer`);
|
|
137
|
+
await promises.writeFile(certPath, content);
|
|
138
|
+
result.certPath = certPath;
|
|
139
|
+
const keyPath = path.join(options.outputDir, `${cert.id}.p12`);
|
|
140
|
+
await promises.writeFile(keyPath, privateKey);
|
|
141
|
+
result.p12Path = keyPath;
|
|
142
|
+
}
|
|
143
|
+
if (options.keychainPath && process.platform === "darwin") {
|
|
144
|
+
await importToKeychain(
|
|
145
|
+
content,
|
|
146
|
+
options.keychainPath,
|
|
147
|
+
options.keychainPassword
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
async function revokeCertificate(client, id) {
|
|
153
|
+
await client.certificates.revoke(id);
|
|
154
|
+
}
|
|
155
|
+
async function downloadCertificate(client, id) {
|
|
156
|
+
const cert = await client.certificates.get(id);
|
|
157
|
+
return Buffer.from(cert.attributes.certificateContent, "base64");
|
|
158
|
+
}
|
|
159
|
+
async function revokeExpiredCertificates(options) {
|
|
160
|
+
const types = resolveCertificateTypes(options);
|
|
161
|
+
const certs = await options.client.certificates.list({
|
|
162
|
+
filter: { certificateType: types }
|
|
163
|
+
});
|
|
164
|
+
const now = /* @__PURE__ */ new Date();
|
|
165
|
+
let count = 0;
|
|
166
|
+
for (const cert of certs) {
|
|
167
|
+
if (new Date(cert.attributes.expirationDate) <= now) {
|
|
168
|
+
try {
|
|
169
|
+
await options.client.certificates.revoke(cert.id);
|
|
170
|
+
count++;
|
|
171
|
+
} catch {
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return count;
|
|
176
|
+
}
|
|
177
|
+
async function importToKeychain(certData, keychainPath, keychainPassword) {
|
|
178
|
+
const { tmpdir: tmpdir2 } = await import('os');
|
|
179
|
+
const tempCertPath = path.join(tmpdir2(), `fastnode-cert-${Date.now()}.cer`);
|
|
180
|
+
await promises.writeFile(tempCertPath, certData);
|
|
181
|
+
try {
|
|
182
|
+
const args = [
|
|
183
|
+
"import",
|
|
184
|
+
tempCertPath,
|
|
185
|
+
"-k",
|
|
186
|
+
keychainPath,
|
|
187
|
+
"-T",
|
|
188
|
+
"/usr/bin/codesign",
|
|
189
|
+
"-T",
|
|
190
|
+
"/usr/bin/security"
|
|
191
|
+
];
|
|
192
|
+
await execFileAsync("security", args);
|
|
193
|
+
if (keychainPassword) {
|
|
194
|
+
await execFileAsync("security", [
|
|
195
|
+
"set-key-partition-list",
|
|
196
|
+
"-S",
|
|
197
|
+
"apple-tool:,apple:,codesign:",
|
|
198
|
+
"-s",
|
|
199
|
+
"-k",
|
|
200
|
+
keychainPassword,
|
|
201
|
+
keychainPath
|
|
202
|
+
]);
|
|
203
|
+
}
|
|
204
|
+
} finally {
|
|
205
|
+
const { unlink } = await import('fs/promises');
|
|
206
|
+
await unlink(tempCertPath).catch(() => {
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
exports.createCertificate = createCertificate;
|
|
212
|
+
exports.downloadCertificate = downloadCertificate;
|
|
213
|
+
exports.findValidCertificates = findValidCertificates;
|
|
214
|
+
exports.generateCSR = generateCSR;
|
|
215
|
+
exports.generateRSACSR = generateRSACSR;
|
|
216
|
+
exports.revokeCertificate = revokeCertificate;
|
|
217
|
+
exports.revokeExpiredCertificates = revokeExpiredCertificates;
|
|
218
|
+
//# sourceMappingURL=index.cjs.map
|
|
219
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cert/csr.ts","../../src/cert/cert.ts"],"names":["x509","webcrypto","generateKeyPairSync","join","tmpdir","writeFileSync","execSync","readFileSync","unlinkSync","promisify","execFile","cert","content","result","mkdir","writeFile"],"mappings":"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","file":"index.cjs","sourcesContent":["import * as x509 from \"@peculiar/x509\";\nimport { webcrypto, generateKeyPairSync } from \"node:crypto\";\nimport { execSync } from \"node:child_process\";\nimport { writeFileSync, readFileSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\n\n// Register the Node.js crypto provider.\nx509.cryptoProvider.set(webcrypto as unknown as Parameters<typeof x509.cryptoProvider.set>[0]);\n\nfunction toPem(header: string, der: Buffer): string {\n const b64 = der.toString(\"base64\");\n const lines: string[] = [];\n for (let i = 0; i < b64.length; i += 64) lines.push(b64.slice(i, i + 64));\n return `-----BEGIN ${header}-----\\n${lines.join(\"\\n\")}\\n-----END ${header}-----`;\n}\n\n/**\n * Generate EC P-256 CSR — used by App Store Connect API (JWT auth).\n */\nexport async function generateCSR(): Promise<{ csr: string; privateKey: string }> {\n const algorithm = { name: \"ECDSA\", namedCurve: \"P-256\" } as const;\n const keyPair = await webcrypto.subtle.generateKey(algorithm, true, [\"sign\", \"verify\"]);\n\n const csr = await x509.Pkcs10CertificateRequestGenerator.create({\n name: \"CN=PEM\",\n keys: keyPair,\n signingAlgorithm: { name: \"ECDSA\", hash: \"SHA-256\" },\n });\n\n const pkcs8 = await webcrypto.subtle.exportKey(\"pkcs8\", keyPair.privateKey);\n return {\n csr: csr.toString(\"pem\"),\n privateKey: toPem(\"PRIVATE KEY\", Buffer.from(pkcs8)),\n };\n}\n\n/**\n * Generate RSA 2048 CSR — required by Apple Developer Portal (session auth).\n * Matches Fastlane's create_certificate_signing_request which uses RSA 2048.\n */\nexport function generateRSACSR(): { csr: string; privateKey: string } {\n const { privateKey, publicKey } = generateKeyPairSync(\"rsa\", {\n modulusLength: 2048,\n privateKeyEncoding: { type: \"pkcs8\", format: \"pem\" },\n publicKeyEncoding: { type: \"spki\", format: \"pem\" },\n });\n\n // Generate CSR using openssl (Node crypto doesn't have native CSR generation for RSA)\n const keyPath = join(tmpdir(), `fastnode-rsa-${Date.now()}.pem`);\n const csrPath = join(tmpdir(), `fastnode-rsa-${Date.now()}.csr`);\n\n try {\n writeFileSync(keyPath, privateKey);\n execSync(`openssl req -new -key \"${keyPath}\" -out \"${csrPath}\" -subj \"/CN=PEM\" 2>/dev/null`);\n const csr = readFileSync(csrPath, \"utf-8\");\n return { csr, privateKey };\n } finally {\n try { unlinkSync(keyPath); } catch {}\n try { unlinkSync(csrPath); } catch {}\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport type { AppStoreConnectClient } from \"../client/index.js\";\nimport type { Certificate, CertificateType } from \"../types/index.js\";\nimport { generateCSR } from \"./csr.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface CertOptions {\n client: AppStoreConnectClient;\n type?: CertificateType;\n development?: boolean;\n force?: boolean;\n outputDir?: string;\n keychainPath?: string;\n keychainPassword?: string;\n platform?: \"ios\" | \"macos\";\n}\n\nexport interface CertResult {\n certificate: Certificate;\n privateKey: string;\n certificateContent: Buffer;\n certPath?: string;\n p12Path?: string;\n}\n\nfunction resolveCertificateTypes(options: CertOptions): CertificateType[] {\n if (options.type) return [options.type];\n\n const platform = options.platform ?? \"ios\";\n if (options.development) {\n return platform === \"macos\" ? [\"MAC_APP_DEVELOPMENT\"] : [\"IOS_DEVELOPMENT\"];\n }\n return platform === \"macos\"\n ? [\"MAC_APP_DISTRIBUTION\"]\n : [\"IOS_DISTRIBUTION\"];\n}\n\nexport async function findValidCertificates(\n options: Omit<CertOptions, \"force\">\n): Promise<Certificate[]> {\n const types = resolveCertificateTypes(options as CertOptions);\n const certs = await options.client.certificates.list({\n filter: { certificateType: types },\n limit: 200,\n });\n\n const now = new Date();\n return certs.filter(\n (c) => new Date(c.attributes.expirationDate) > now\n );\n}\n\nexport async function createCertificate(\n options: CertOptions\n): Promise<CertResult> {\n // Check for existing valid certs unless force\n if (!options.force) {\n const existing = await findValidCertificates(options);\n if (existing.length > 0) {\n const cert = existing[0];\n const content = Buffer.from(cert.attributes.certificateContent, \"base64\");\n const result: CertResult = {\n certificate: cert,\n privateKey: \"\",\n certificateContent: content,\n };\n\n if (options.outputDir) {\n await mkdir(options.outputDir, { recursive: true });\n const certPath = join(options.outputDir, `${cert.id}.cer`);\n await writeFile(certPath, content);\n result.certPath = certPath;\n }\n\n return result;\n }\n }\n\n // Generate CSR and create new certificate\n const types = resolveCertificateTypes(options);\n const { csr, privateKey } = await generateCSR();\n\n const cert = await options.client.certificates.create({\n certificateType: types[0],\n csrContent: csr,\n });\n\n const content = Buffer.from(cert.attributes.certificateContent, \"base64\");\n\n const result: CertResult = {\n certificate: cert,\n privateKey,\n certificateContent: content,\n };\n\n // Write files if outputDir provided\n if (options.outputDir) {\n await mkdir(options.outputDir, { recursive: true });\n\n const certPath = join(options.outputDir, `${cert.id}.cer`);\n await writeFile(certPath, content);\n result.certPath = certPath;\n\n const keyPath = join(options.outputDir, `${cert.id}.p12`);\n await writeFile(keyPath, privateKey);\n result.p12Path = keyPath;\n }\n\n // Import to keychain if on macOS\n if (options.keychainPath && process.platform === \"darwin\") {\n await importToKeychain(\n content,\n options.keychainPath,\n options.keychainPassword\n );\n }\n\n return result;\n}\n\nexport async function revokeCertificate(\n client: AppStoreConnectClient,\n id: string\n): Promise<void> {\n await client.certificates.revoke(id);\n}\n\nexport async function downloadCertificate(\n client: AppStoreConnectClient,\n id: string\n): Promise<Buffer> {\n const cert = await client.certificates.get(id);\n return Buffer.from(cert.attributes.certificateContent, \"base64\");\n}\n\nexport async function revokeExpiredCertificates(\n options: CertOptions\n): Promise<number> {\n const types = resolveCertificateTypes(options);\n const certs = await options.client.certificates.list({\n filter: { certificateType: types },\n });\n\n const now = new Date();\n let count = 0;\n for (const cert of certs) {\n if (new Date(cert.attributes.expirationDate) <= now) {\n try {\n await options.client.certificates.revoke(cert.id);\n count++;\n } catch {\n // Ignore revocation failures for already-revoked certs\n }\n }\n }\n return count;\n}\n\nasync function importToKeychain(\n certData: Buffer,\n keychainPath: string,\n keychainPassword?: string\n): Promise<void> {\n const { tmpdir } = await import(\"node:os\");\n const tempCertPath = join(tmpdir(), `fastnode-cert-${Date.now()}.cer`);\n await writeFile(tempCertPath, certData);\n\n try {\n const args = [\n \"import\",\n tempCertPath,\n \"-k\",\n keychainPath,\n \"-T\",\n \"/usr/bin/codesign\",\n \"-T\",\n \"/usr/bin/security\",\n ];\n\n await execFileAsync(\"security\", args);\n\n // Set partition list if keychain password provided\n if (keychainPassword) {\n await execFileAsync(\"security\", [\n \"set-key-partition-list\",\n \"-S\",\n \"apple-tool:,apple:,codesign:\",\n \"-s\",\n \"-k\",\n keychainPassword,\n keychainPath,\n ]);\n }\n } finally {\n const { unlink } = await import(\"node:fs/promises\");\n await unlink(tempCertPath).catch(() => {});\n }\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { C as CertOptions, a as CertResult, c as createCertificate, d as downloadCertificate, f as findValidCertificates, r as revokeCertificate, b as revokeExpiredCertificates } from '../cert-BmJGtYtb.cjs';
|
|
2
|
+
export { g as generateCSR, a as generateRSACSR } from '../index-lt819Jgj.cjs';
|
|
3
|
+
import '../index-BLubSlgK.cjs';
|
|
4
|
+
import '../enums-B609j2rb.cjs';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { C as CertOptions, a as CertResult, c as createCertificate, d as downloadCertificate, f as findValidCertificates, r as revokeCertificate, b as revokeExpiredCertificates } from '../cert-owkOFNW8.js';
|
|
2
|
+
export { g as generateCSR, a as generateRSACSR } from '../index-DfirmFbC.js';
|
|
3
|
+
import '../index-D1Izm7qt.js';
|
|
4
|
+
import '../enums-B609j2rb.js';
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { execFile, execSync } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { mkdir, writeFile } from 'fs/promises';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import * as x509 from '@peculiar/x509';
|
|
6
|
+
import { webcrypto, generateKeyPairSync } from 'crypto';
|
|
7
|
+
import { writeFileSync, readFileSync, unlinkSync } from 'fs';
|
|
8
|
+
import { tmpdir } from 'os';
|
|
9
|
+
|
|
10
|
+
// src/cert/cert.ts
|
|
11
|
+
x509.cryptoProvider.set(webcrypto);
|
|
12
|
+
function toPem(header, der) {
|
|
13
|
+
const b64 = der.toString("base64");
|
|
14
|
+
const lines = [];
|
|
15
|
+
for (let i = 0; i < b64.length; i += 64) lines.push(b64.slice(i, i + 64));
|
|
16
|
+
return `-----BEGIN ${header}-----
|
|
17
|
+
${lines.join("\n")}
|
|
18
|
+
-----END ${header}-----`;
|
|
19
|
+
}
|
|
20
|
+
async function generateCSR() {
|
|
21
|
+
const algorithm = { name: "ECDSA", namedCurve: "P-256" };
|
|
22
|
+
const keyPair = await webcrypto.subtle.generateKey(algorithm, true, ["sign", "verify"]);
|
|
23
|
+
const csr = await x509.Pkcs10CertificateRequestGenerator.create({
|
|
24
|
+
name: "CN=PEM",
|
|
25
|
+
keys: keyPair,
|
|
26
|
+
signingAlgorithm: { name: "ECDSA", hash: "SHA-256" }
|
|
27
|
+
});
|
|
28
|
+
const pkcs8 = await webcrypto.subtle.exportKey("pkcs8", keyPair.privateKey);
|
|
29
|
+
return {
|
|
30
|
+
csr: csr.toString("pem"),
|
|
31
|
+
privateKey: toPem("PRIVATE KEY", Buffer.from(pkcs8))
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function generateRSACSR() {
|
|
35
|
+
const { privateKey, publicKey } = generateKeyPairSync("rsa", {
|
|
36
|
+
modulusLength: 2048,
|
|
37
|
+
privateKeyEncoding: { type: "pkcs8", format: "pem" },
|
|
38
|
+
publicKeyEncoding: { type: "spki", format: "pem" }
|
|
39
|
+
});
|
|
40
|
+
const keyPath = join(tmpdir(), `fastnode-rsa-${Date.now()}.pem`);
|
|
41
|
+
const csrPath = join(tmpdir(), `fastnode-rsa-${Date.now()}.csr`);
|
|
42
|
+
try {
|
|
43
|
+
writeFileSync(keyPath, privateKey);
|
|
44
|
+
execSync(`openssl req -new -key "${keyPath}" -out "${csrPath}" -subj "/CN=PEM" 2>/dev/null`);
|
|
45
|
+
const csr = readFileSync(csrPath, "utf-8");
|
|
46
|
+
return { csr, privateKey };
|
|
47
|
+
} finally {
|
|
48
|
+
try {
|
|
49
|
+
unlinkSync(keyPath);
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
unlinkSync(csrPath);
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/cert/cert.ts
|
|
60
|
+
var execFileAsync = promisify(execFile);
|
|
61
|
+
function resolveCertificateTypes(options) {
|
|
62
|
+
if (options.type) return [options.type];
|
|
63
|
+
const platform = options.platform ?? "ios";
|
|
64
|
+
if (options.development) {
|
|
65
|
+
return platform === "macos" ? ["MAC_APP_DEVELOPMENT"] : ["IOS_DEVELOPMENT"];
|
|
66
|
+
}
|
|
67
|
+
return platform === "macos" ? ["MAC_APP_DISTRIBUTION"] : ["IOS_DISTRIBUTION"];
|
|
68
|
+
}
|
|
69
|
+
async function findValidCertificates(options) {
|
|
70
|
+
const types = resolveCertificateTypes(options);
|
|
71
|
+
const certs = await options.client.certificates.list({
|
|
72
|
+
filter: { certificateType: types },
|
|
73
|
+
limit: 200
|
|
74
|
+
});
|
|
75
|
+
const now = /* @__PURE__ */ new Date();
|
|
76
|
+
return certs.filter(
|
|
77
|
+
(c) => new Date(c.attributes.expirationDate) > now
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
async function createCertificate(options) {
|
|
81
|
+
if (!options.force) {
|
|
82
|
+
const existing = await findValidCertificates(options);
|
|
83
|
+
if (existing.length > 0) {
|
|
84
|
+
const cert2 = existing[0];
|
|
85
|
+
const content2 = Buffer.from(cert2.attributes.certificateContent, "base64");
|
|
86
|
+
const result2 = {
|
|
87
|
+
certificate: cert2,
|
|
88
|
+
privateKey: "",
|
|
89
|
+
certificateContent: content2
|
|
90
|
+
};
|
|
91
|
+
if (options.outputDir) {
|
|
92
|
+
await mkdir(options.outputDir, { recursive: true });
|
|
93
|
+
const certPath = join(options.outputDir, `${cert2.id}.cer`);
|
|
94
|
+
await writeFile(certPath, content2);
|
|
95
|
+
result2.certPath = certPath;
|
|
96
|
+
}
|
|
97
|
+
return result2;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const types = resolveCertificateTypes(options);
|
|
101
|
+
const { csr, privateKey } = await generateCSR();
|
|
102
|
+
const cert = await options.client.certificates.create({
|
|
103
|
+
certificateType: types[0],
|
|
104
|
+
csrContent: csr
|
|
105
|
+
});
|
|
106
|
+
const content = Buffer.from(cert.attributes.certificateContent, "base64");
|
|
107
|
+
const result = {
|
|
108
|
+
certificate: cert,
|
|
109
|
+
privateKey,
|
|
110
|
+
certificateContent: content
|
|
111
|
+
};
|
|
112
|
+
if (options.outputDir) {
|
|
113
|
+
await mkdir(options.outputDir, { recursive: true });
|
|
114
|
+
const certPath = join(options.outputDir, `${cert.id}.cer`);
|
|
115
|
+
await writeFile(certPath, content);
|
|
116
|
+
result.certPath = certPath;
|
|
117
|
+
const keyPath = join(options.outputDir, `${cert.id}.p12`);
|
|
118
|
+
await writeFile(keyPath, privateKey);
|
|
119
|
+
result.p12Path = keyPath;
|
|
120
|
+
}
|
|
121
|
+
if (options.keychainPath && process.platform === "darwin") {
|
|
122
|
+
await importToKeychain(
|
|
123
|
+
content,
|
|
124
|
+
options.keychainPath,
|
|
125
|
+
options.keychainPassword
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
async function revokeCertificate(client, id) {
|
|
131
|
+
await client.certificates.revoke(id);
|
|
132
|
+
}
|
|
133
|
+
async function downloadCertificate(client, id) {
|
|
134
|
+
const cert = await client.certificates.get(id);
|
|
135
|
+
return Buffer.from(cert.attributes.certificateContent, "base64");
|
|
136
|
+
}
|
|
137
|
+
async function revokeExpiredCertificates(options) {
|
|
138
|
+
const types = resolveCertificateTypes(options);
|
|
139
|
+
const certs = await options.client.certificates.list({
|
|
140
|
+
filter: { certificateType: types }
|
|
141
|
+
});
|
|
142
|
+
const now = /* @__PURE__ */ new Date();
|
|
143
|
+
let count = 0;
|
|
144
|
+
for (const cert of certs) {
|
|
145
|
+
if (new Date(cert.attributes.expirationDate) <= now) {
|
|
146
|
+
try {
|
|
147
|
+
await options.client.certificates.revoke(cert.id);
|
|
148
|
+
count++;
|
|
149
|
+
} catch {
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return count;
|
|
154
|
+
}
|
|
155
|
+
async function importToKeychain(certData, keychainPath, keychainPassword) {
|
|
156
|
+
const { tmpdir: tmpdir2 } = await import('os');
|
|
157
|
+
const tempCertPath = join(tmpdir2(), `fastnode-cert-${Date.now()}.cer`);
|
|
158
|
+
await writeFile(tempCertPath, certData);
|
|
159
|
+
try {
|
|
160
|
+
const args = [
|
|
161
|
+
"import",
|
|
162
|
+
tempCertPath,
|
|
163
|
+
"-k",
|
|
164
|
+
keychainPath,
|
|
165
|
+
"-T",
|
|
166
|
+
"/usr/bin/codesign",
|
|
167
|
+
"-T",
|
|
168
|
+
"/usr/bin/security"
|
|
169
|
+
];
|
|
170
|
+
await execFileAsync("security", args);
|
|
171
|
+
if (keychainPassword) {
|
|
172
|
+
await execFileAsync("security", [
|
|
173
|
+
"set-key-partition-list",
|
|
174
|
+
"-S",
|
|
175
|
+
"apple-tool:,apple:,codesign:",
|
|
176
|
+
"-s",
|
|
177
|
+
"-k",
|
|
178
|
+
keychainPassword,
|
|
179
|
+
keychainPath
|
|
180
|
+
]);
|
|
181
|
+
}
|
|
182
|
+
} finally {
|
|
183
|
+
const { unlink } = await import('fs/promises');
|
|
184
|
+
await unlink(tempCertPath).catch(() => {
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export { createCertificate, downloadCertificate, findValidCertificates, generateCSR, generateRSACSR, revokeCertificate, revokeExpiredCertificates };
|
|
190
|
+
//# sourceMappingURL=index.mjs.map
|
|
191
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cert/csr.ts","../../src/cert/cert.ts"],"names":["cert","content","result","join","tmpdir"],"mappings":"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","file":"index.mjs","sourcesContent":["import * as x509 from \"@peculiar/x509\";\nimport { webcrypto, generateKeyPairSync } from \"node:crypto\";\nimport { execSync } from \"node:child_process\";\nimport { writeFileSync, readFileSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\n\n// Register the Node.js crypto provider.\nx509.cryptoProvider.set(webcrypto as unknown as Parameters<typeof x509.cryptoProvider.set>[0]);\n\nfunction toPem(header: string, der: Buffer): string {\n const b64 = der.toString(\"base64\");\n const lines: string[] = [];\n for (let i = 0; i < b64.length; i += 64) lines.push(b64.slice(i, i + 64));\n return `-----BEGIN ${header}-----\\n${lines.join(\"\\n\")}\\n-----END ${header}-----`;\n}\n\n/**\n * Generate EC P-256 CSR — used by App Store Connect API (JWT auth).\n */\nexport async function generateCSR(): Promise<{ csr: string; privateKey: string }> {\n const algorithm = { name: \"ECDSA\", namedCurve: \"P-256\" } as const;\n const keyPair = await webcrypto.subtle.generateKey(algorithm, true, [\"sign\", \"verify\"]);\n\n const csr = await x509.Pkcs10CertificateRequestGenerator.create({\n name: \"CN=PEM\",\n keys: keyPair,\n signingAlgorithm: { name: \"ECDSA\", hash: \"SHA-256\" },\n });\n\n const pkcs8 = await webcrypto.subtle.exportKey(\"pkcs8\", keyPair.privateKey);\n return {\n csr: csr.toString(\"pem\"),\n privateKey: toPem(\"PRIVATE KEY\", Buffer.from(pkcs8)),\n };\n}\n\n/**\n * Generate RSA 2048 CSR — required by Apple Developer Portal (session auth).\n * Matches Fastlane's create_certificate_signing_request which uses RSA 2048.\n */\nexport function generateRSACSR(): { csr: string; privateKey: string } {\n const { privateKey, publicKey } = generateKeyPairSync(\"rsa\", {\n modulusLength: 2048,\n privateKeyEncoding: { type: \"pkcs8\", format: \"pem\" },\n publicKeyEncoding: { type: \"spki\", format: \"pem\" },\n });\n\n // Generate CSR using openssl (Node crypto doesn't have native CSR generation for RSA)\n const keyPath = join(tmpdir(), `fastnode-rsa-${Date.now()}.pem`);\n const csrPath = join(tmpdir(), `fastnode-rsa-${Date.now()}.csr`);\n\n try {\n writeFileSync(keyPath, privateKey);\n execSync(`openssl req -new -key \"${keyPath}\" -out \"${csrPath}\" -subj \"/CN=PEM\" 2>/dev/null`);\n const csr = readFileSync(csrPath, \"utf-8\");\n return { csr, privateKey };\n } finally {\n try { unlinkSync(keyPath); } catch {}\n try { unlinkSync(csrPath); } catch {}\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport type { AppStoreConnectClient } from \"../client/index.js\";\nimport type { Certificate, CertificateType } from \"../types/index.js\";\nimport { generateCSR } from \"./csr.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface CertOptions {\n client: AppStoreConnectClient;\n type?: CertificateType;\n development?: boolean;\n force?: boolean;\n outputDir?: string;\n keychainPath?: string;\n keychainPassword?: string;\n platform?: \"ios\" | \"macos\";\n}\n\nexport interface CertResult {\n certificate: Certificate;\n privateKey: string;\n certificateContent: Buffer;\n certPath?: string;\n p12Path?: string;\n}\n\nfunction resolveCertificateTypes(options: CertOptions): CertificateType[] {\n if (options.type) return [options.type];\n\n const platform = options.platform ?? \"ios\";\n if (options.development) {\n return platform === \"macos\" ? [\"MAC_APP_DEVELOPMENT\"] : [\"IOS_DEVELOPMENT\"];\n }\n return platform === \"macos\"\n ? [\"MAC_APP_DISTRIBUTION\"]\n : [\"IOS_DISTRIBUTION\"];\n}\n\nexport async function findValidCertificates(\n options: Omit<CertOptions, \"force\">\n): Promise<Certificate[]> {\n const types = resolveCertificateTypes(options as CertOptions);\n const certs = await options.client.certificates.list({\n filter: { certificateType: types },\n limit: 200,\n });\n\n const now = new Date();\n return certs.filter(\n (c) => new Date(c.attributes.expirationDate) > now\n );\n}\n\nexport async function createCertificate(\n options: CertOptions\n): Promise<CertResult> {\n // Check for existing valid certs unless force\n if (!options.force) {\n const existing = await findValidCertificates(options);\n if (existing.length > 0) {\n const cert = existing[0];\n const content = Buffer.from(cert.attributes.certificateContent, \"base64\");\n const result: CertResult = {\n certificate: cert,\n privateKey: \"\",\n certificateContent: content,\n };\n\n if (options.outputDir) {\n await mkdir(options.outputDir, { recursive: true });\n const certPath = join(options.outputDir, `${cert.id}.cer`);\n await writeFile(certPath, content);\n result.certPath = certPath;\n }\n\n return result;\n }\n }\n\n // Generate CSR and create new certificate\n const types = resolveCertificateTypes(options);\n const { csr, privateKey } = await generateCSR();\n\n const cert = await options.client.certificates.create({\n certificateType: types[0],\n csrContent: csr,\n });\n\n const content = Buffer.from(cert.attributes.certificateContent, \"base64\");\n\n const result: CertResult = {\n certificate: cert,\n privateKey,\n certificateContent: content,\n };\n\n // Write files if outputDir provided\n if (options.outputDir) {\n await mkdir(options.outputDir, { recursive: true });\n\n const certPath = join(options.outputDir, `${cert.id}.cer`);\n await writeFile(certPath, content);\n result.certPath = certPath;\n\n const keyPath = join(options.outputDir, `${cert.id}.p12`);\n await writeFile(keyPath, privateKey);\n result.p12Path = keyPath;\n }\n\n // Import to keychain if on macOS\n if (options.keychainPath && process.platform === \"darwin\") {\n await importToKeychain(\n content,\n options.keychainPath,\n options.keychainPassword\n );\n }\n\n return result;\n}\n\nexport async function revokeCertificate(\n client: AppStoreConnectClient,\n id: string\n): Promise<void> {\n await client.certificates.revoke(id);\n}\n\nexport async function downloadCertificate(\n client: AppStoreConnectClient,\n id: string\n): Promise<Buffer> {\n const cert = await client.certificates.get(id);\n return Buffer.from(cert.attributes.certificateContent, \"base64\");\n}\n\nexport async function revokeExpiredCertificates(\n options: CertOptions\n): Promise<number> {\n const types = resolveCertificateTypes(options);\n const certs = await options.client.certificates.list({\n filter: { certificateType: types },\n });\n\n const now = new Date();\n let count = 0;\n for (const cert of certs) {\n if (new Date(cert.attributes.expirationDate) <= now) {\n try {\n await options.client.certificates.revoke(cert.id);\n count++;\n } catch {\n // Ignore revocation failures for already-revoked certs\n }\n }\n }\n return count;\n}\n\nasync function importToKeychain(\n certData: Buffer,\n keychainPath: string,\n keychainPassword?: string\n): Promise<void> {\n const { tmpdir } = await import(\"node:os\");\n const tempCertPath = join(tmpdir(), `fastnode-cert-${Date.now()}.cer`);\n await writeFile(tempCertPath, certData);\n\n try {\n const args = [\n \"import\",\n tempCertPath,\n \"-k\",\n keychainPath,\n \"-T\",\n \"/usr/bin/codesign\",\n \"-T\",\n \"/usr/bin/security\",\n ];\n\n await execFileAsync(\"security\", args);\n\n // Set partition list if keychain password provided\n if (keychainPassword) {\n await execFileAsync(\"security\", [\n \"set-key-partition-list\",\n \"-S\",\n \"apple-tool:,apple:,codesign:\",\n \"-s\",\n \"-k\",\n keychainPassword,\n keychainPath,\n ]);\n }\n } finally {\n const { unlink } = await import(\"node:fs/promises\");\n await unlink(tempCertPath).catch(() => {});\n }\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { A as AppStoreConnectClient, C as Certificate } from './index-BLubSlgK.cjs';
|
|
2
|
+
import { C as CertificateType } from './enums-B609j2rb.cjs';
|
|
3
|
+
|
|
4
|
+
interface CertOptions {
|
|
5
|
+
client: AppStoreConnectClient;
|
|
6
|
+
type?: CertificateType;
|
|
7
|
+
development?: boolean;
|
|
8
|
+
force?: boolean;
|
|
9
|
+
outputDir?: string;
|
|
10
|
+
keychainPath?: string;
|
|
11
|
+
keychainPassword?: string;
|
|
12
|
+
platform?: "ios" | "macos";
|
|
13
|
+
}
|
|
14
|
+
interface CertResult {
|
|
15
|
+
certificate: Certificate;
|
|
16
|
+
privateKey: string;
|
|
17
|
+
certificateContent: Buffer;
|
|
18
|
+
certPath?: string;
|
|
19
|
+
p12Path?: string;
|
|
20
|
+
}
|
|
21
|
+
declare function findValidCertificates(options: Omit<CertOptions, "force">): Promise<Certificate[]>;
|
|
22
|
+
declare function createCertificate(options: CertOptions): Promise<CertResult>;
|
|
23
|
+
declare function revokeCertificate(client: AppStoreConnectClient, id: string): Promise<void>;
|
|
24
|
+
declare function downloadCertificate(client: AppStoreConnectClient, id: string): Promise<Buffer>;
|
|
25
|
+
declare function revokeExpiredCertificates(options: CertOptions): Promise<number>;
|
|
26
|
+
|
|
27
|
+
export { type CertOptions as C, type CertResult as a, revokeExpiredCertificates as b, createCertificate as c, downloadCertificate as d, findValidCertificates as f, revokeCertificate as r };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { A as AppStoreConnectClient, C as Certificate } from './index-D1Izm7qt.js';
|
|
2
|
+
import { C as CertificateType } from './enums-B609j2rb.js';
|
|
3
|
+
|
|
4
|
+
interface CertOptions {
|
|
5
|
+
client: AppStoreConnectClient;
|
|
6
|
+
type?: CertificateType;
|
|
7
|
+
development?: boolean;
|
|
8
|
+
force?: boolean;
|
|
9
|
+
outputDir?: string;
|
|
10
|
+
keychainPath?: string;
|
|
11
|
+
keychainPassword?: string;
|
|
12
|
+
platform?: "ios" | "macos";
|
|
13
|
+
}
|
|
14
|
+
interface CertResult {
|
|
15
|
+
certificate: Certificate;
|
|
16
|
+
privateKey: string;
|
|
17
|
+
certificateContent: Buffer;
|
|
18
|
+
certPath?: string;
|
|
19
|
+
p12Path?: string;
|
|
20
|
+
}
|
|
21
|
+
declare function findValidCertificates(options: Omit<CertOptions, "force">): Promise<Certificate[]>;
|
|
22
|
+
declare function createCertificate(options: CertOptions): Promise<CertResult>;
|
|
23
|
+
declare function revokeCertificate(client: AppStoreConnectClient, id: string): Promise<void>;
|
|
24
|
+
declare function downloadCertificate(client: AppStoreConnectClient, id: string): Promise<Buffer>;
|
|
25
|
+
declare function revokeExpiredCertificates(options: CertOptions): Promise<number>;
|
|
26
|
+
|
|
27
|
+
export { type CertOptions as C, type CertResult as a, revokeExpiredCertificates as b, createCertificate as c, downloadCertificate as d, findValidCertificates as f, revokeCertificate as r };
|