@sitepong/fastnode 0.1.2 → 0.2.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.
Files changed (70) hide show
  1. package/README.md +148 -0
  2. package/dist/actions/index.cjs +758 -110
  3. package/dist/actions/index.cjs.map +1 -1
  4. package/dist/actions/index.mjs +758 -110
  5. package/dist/actions/index.mjs.map +1 -1
  6. package/dist/cert/index.cjs +40 -0
  7. package/dist/cert/index.cjs.map +1 -1
  8. package/dist/cert/index.d.cts +3 -3
  9. package/dist/cert/index.d.ts +3 -3
  10. package/dist/cert/index.mjs +37 -1
  11. package/dist/cert/index.mjs.map +1 -1
  12. package/dist/{cert-owkOFNW8.d.ts → cert-e5GAgAPb.d.ts} +1 -1
  13. package/dist/{cert-BmJGtYtb.d.cts → cert-uLLdb5a7.d.cts} +1 -1
  14. package/dist/cli/index.cjs +758 -110
  15. package/dist/cli/index.cjs.map +1 -1
  16. package/dist/cli/index.d.cts +1 -1
  17. package/dist/cli/index.d.ts +1 -1
  18. package/dist/cli/index.mjs +758 -110
  19. package/dist/cli/index.mjs.map +1 -1
  20. package/dist/client/index.cjs +751 -109
  21. package/dist/client/index.cjs.map +1 -1
  22. package/dist/client/index.d.cts +1 -1
  23. package/dist/client/index.d.ts +1 -1
  24. package/dist/client/index.mjs +747 -110
  25. package/dist/client/index.mjs.map +1 -1
  26. package/dist/deliver/index.d.cts +2 -2
  27. package/dist/deliver/index.d.ts +2 -2
  28. package/dist/{index-BFdNOmPJ.d.cts → index-BN0iWhuw.d.cts} +1 -1
  29. package/dist/index-BNP7Bpu5.d.ts +61 -0
  30. package/dist/{index-1Vu2cRQ2.d.ts → index-BbY_H_f6.d.ts} +1 -1
  31. package/dist/{index-D6zjGlPL.d.cts → index-BgHagzj1.d.cts} +1 -1
  32. package/dist/{index-D5eihzwM.d.cts → index-BjkOUQcQ.d.cts} +1 -1
  33. package/dist/{index-D1Izm7qt.d.ts → index-BwwpAlk2.d.ts} +363 -2
  34. package/dist/{index-A5MimeQk.d.ts → index-C2YLoFVl.d.ts} +1 -1
  35. package/dist/{index-TfXqwuac.d.ts → index-CEldrbyz.d.ts} +1 -1
  36. package/dist/{index-BLubSlgK.d.cts → index-CdfgEZwh.d.cts} +363 -2
  37. package/dist/{index-DfCUVJX1.d.cts → index-Clyf4-lu.d.cts} +1 -1
  38. package/dist/index-CtydPNxA.d.cts +61 -0
  39. package/dist/{index-BQJIJlK7.d.cts → index-DHxi-QPC.d.cts} +3 -3
  40. package/dist/{index-BN0ubxjZ.d.ts → index-Di4Ic0EE.d.ts} +3 -3
  41. package/dist/{index-EcVvViW8.d.cts → index-DrCOh0Vh.d.cts} +1 -1
  42. package/dist/{index-B0yhu_LZ.d.ts → index-EKU_G1G5.d.ts} +1 -1
  43. package/dist/{index-CWNLnSOL.d.cts → index-XsMsVc3O.d.cts} +1 -1
  44. package/dist/{index-B9yXicrQ.d.ts → index-jeI44Q5G.d.ts} +1 -1
  45. package/dist/{index-DHw08dUc.d.ts → index-mddpvrRX.d.ts} +1 -1
  46. package/dist/index.cjs +1233 -110
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.d.cts +226 -10
  49. package/dist/index.d.ts +226 -10
  50. package/dist/index.mjs +1230 -111
  51. package/dist/index.mjs.map +1 -1
  52. package/dist/lane/index.cjs +758 -110
  53. package/dist/lane/index.cjs.map +1 -1
  54. package/dist/lane/index.mjs +758 -110
  55. package/dist/lane/index.mjs.map +1 -1
  56. package/dist/match/index.d.cts +4 -4
  57. package/dist/match/index.d.ts +4 -4
  58. package/dist/pem/index.d.cts +2 -2
  59. package/dist/pem/index.d.ts +2 -2
  60. package/dist/pilot/index.d.cts +2 -2
  61. package/dist/pilot/index.d.ts +2 -2
  62. package/dist/precheck/index.d.cts +2 -2
  63. package/dist/precheck/index.d.ts +2 -2
  64. package/dist/produce/index.d.cts +2 -2
  65. package/dist/produce/index.d.ts +2 -2
  66. package/dist/sigh/index.d.cts +2 -2
  67. package/dist/sigh/index.d.ts +2 -2
  68. package/package.json +3 -1
  69. package/dist/index-DfirmFbC.d.ts +0 -32
  70. package/dist/index-lt819Jgj.d.cts +0 -32
@@ -8,6 +8,9 @@ var x509 = require('@peculiar/x509');
8
8
  var crypto = require('crypto');
9
9
  var fs = require('fs');
10
10
  var os = require('os');
11
+ var forge = require('node-forge');
12
+
13
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
14
 
12
15
  function _interopNamespace(e) {
13
16
  if (e && e.__esModule) return e;
@@ -28,6 +31,7 @@ function _interopNamespace(e) {
28
31
  }
29
32
 
30
33
  var x509__namespace = /*#__PURE__*/_interopNamespace(x509);
34
+ var forge__default = /*#__PURE__*/_interopDefault(forge);
31
35
 
32
36
  // src/cert/cert.ts
33
37
  x509__namespace.cryptoProvider.set(crypto.webcrypto);
@@ -207,7 +211,43 @@ async function importToKeychain(certData, keychainPath, keychainPassword) {
207
211
  });
208
212
  }
209
213
  }
214
+ function derBufferToPem(der) {
215
+ const b64 = der.toString("base64");
216
+ const lines = [];
217
+ for (let i = 0; i < b64.length; i += 64) lines.push(b64.slice(i, i + 64));
218
+ return `-----BEGIN CERTIFICATE-----
219
+ ${lines.join("\n")}
220
+ -----END CERTIFICATE-----
221
+ `;
222
+ }
223
+ function normalizeCertPem(input) {
224
+ if (typeof input === "string") {
225
+ if (input.includes("BEGIN CERTIFICATE")) return input;
226
+ const b64 = input.replace(/\s+/g, "");
227
+ return derBufferToPem(Buffer.from(b64, "base64"));
228
+ }
229
+ return derBufferToPem(input);
230
+ }
231
+ function bundleP12(options) {
232
+ const certPem = normalizeCertPem(options.certificate);
233
+ const cert = forge__default.default.pki.certificateFromPem(certPem);
234
+ const privateKey = forge__default.default.pki.privateKeyFromPem(options.privateKeyPem);
235
+ const friendlyName = options.friendlyName ?? "fastnode signing identity";
236
+ const p12Asn1 = forge__default.default.pkcs12.toPkcs12Asn1(
237
+ privateKey,
238
+ [cert],
239
+ options.password,
240
+ {
241
+ friendlyName,
242
+ generateLocalKeyId: true,
243
+ algorithm: "3des"
244
+ }
245
+ );
246
+ const der = forge__default.default.asn1.toDer(p12Asn1).getBytes();
247
+ return Buffer.from(der, "binary");
248
+ }
210
249
 
250
+ exports.bundleP12 = bundleP12;
211
251
  exports.createCertificate = createCertificate;
212
252
  exports.downloadCertificate = downloadCertificate;
213
253
  exports.findValidCertificates = findValidCertificates;
@@ -1 +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"]}
1
+ {"version":3,"sources":["../../src/cert/csr.ts","../../src/cert/cert.ts","../../src/cert/p12.ts"],"names":["x509","webcrypto","generateKeyPairSync","join","tmpdir","writeFileSync","execSync","readFileSync","unlinkSync","promisify","execFile","cert","content","result","mkdir","writeFile","forge"],"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","/**\n * PKCS#12 (.p12) packaging — bundles a certificate + private key into an\n * encrypted .p12 file, which is the format Apple's codesign, xcodebuild,\n * and Fastlane's cert action all expect for distribution signing.\n *\n * Uses node-forge's pkcs12.toPkcs12Asn1 which emits the legacy-compatible\n * format (3DES + RC2) that Keychain Access, iTMSTransporter, and older\n * Apple tooling accept. OpenSSL 3's default format requires the -legacy\n * flag and is not portable; node-forge sidesteps that entirely.\n */\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore — node-forge ships its own types but not ESM-friendly\nimport forge from \"node-forge\";\n\nexport interface BundleP12Options {\n /** Certificate: PEM string, or raw DER Buffer as returned by PortalClient.downloadCertificate */\n certificate: Buffer | string;\n /** PEM-encoded RSA private key (as produced by generateRSACSR) */\n privateKeyPem: string;\n /** Password used to encrypt the .p12 */\n password: string;\n /** Friendly name embedded in the bag (shown in Keychain Access) */\n friendlyName?: string;\n}\n\nfunction derBufferToPem(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 CERTIFICATE-----\\n${lines.join(\"\\n\")}\\n-----END CERTIFICATE-----\\n`;\n}\n\nfunction normalizeCertPem(input: Buffer | string): string {\n if (typeof input === \"string\") {\n if (input.includes(\"BEGIN CERTIFICATE\")) return input;\n // Raw base64 string without headers\n const b64 = input.replace(/\\s+/g, \"\");\n return derBufferToPem(Buffer.from(b64, \"base64\"));\n }\n return derBufferToPem(input);\n}\n\n/**\n * Create a PKCS#12 buffer containing the given cert + private key,\n * encrypted with `password`. Returns a Buffer suitable for writing to\n * disk or uploading as a form field.\n */\nexport function bundleP12(options: BundleP12Options): Buffer {\n const certPem = normalizeCertPem(options.certificate);\n const cert = forge.pki.certificateFromPem(certPem);\n const privateKey = forge.pki.privateKeyFromPem(options.privateKeyPem);\n\n const friendlyName = options.friendlyName ?? \"fastnode signing identity\";\n\n // node-forge picks 3DES for keys and RC2 for certs by default, which is\n // exactly what legacy Apple tooling expects. We pass friendlyName via the\n // bag attributes so Keychain Access shows a readable name.\n const p12Asn1 = forge.pkcs12.toPkcs12Asn1(\n privateKey,\n [cert],\n options.password,\n {\n friendlyName,\n generateLocalKeyId: true,\n algorithm: \"3des\",\n }\n );\n const der = forge.asn1.toDer(p12Asn1).getBytes();\n return Buffer.from(der, \"binary\");\n}\n"]}
@@ -1,4 +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';
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-uLLdb5a7.cjs';
2
+ export { B as BundleP12Options, b as bundleP12, g as generateCSR, a as generateRSACSR } from '../index-CtydPNxA.cjs';
3
+ import '../index-CdfgEZwh.cjs';
4
4
  import '../enums-B609j2rb.cjs';
@@ -1,4 +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';
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-e5GAgAPb.js';
2
+ export { B as BundleP12Options, b as bundleP12, g as generateCSR, a as generateRSACSR } from '../index-BNP7Bpu5.js';
3
+ import '../index-BwwpAlk2.js';
4
4
  import '../enums-B609j2rb.js';
@@ -6,6 +6,7 @@ import * as x509 from '@peculiar/x509';
6
6
  import { webcrypto, generateKeyPairSync } from 'crypto';
7
7
  import { writeFileSync, readFileSync, unlinkSync } from 'fs';
8
8
  import { tmpdir } from 'os';
9
+ import forge from 'node-forge';
9
10
 
10
11
  // src/cert/cert.ts
11
12
  x509.cryptoProvider.set(webcrypto);
@@ -185,7 +186,42 @@ async function importToKeychain(certData, keychainPath, keychainPassword) {
185
186
  });
186
187
  }
187
188
  }
189
+ function derBufferToPem(der) {
190
+ const b64 = der.toString("base64");
191
+ const lines = [];
192
+ for (let i = 0; i < b64.length; i += 64) lines.push(b64.slice(i, i + 64));
193
+ return `-----BEGIN CERTIFICATE-----
194
+ ${lines.join("\n")}
195
+ -----END CERTIFICATE-----
196
+ `;
197
+ }
198
+ function normalizeCertPem(input) {
199
+ if (typeof input === "string") {
200
+ if (input.includes("BEGIN CERTIFICATE")) return input;
201
+ const b64 = input.replace(/\s+/g, "");
202
+ return derBufferToPem(Buffer.from(b64, "base64"));
203
+ }
204
+ return derBufferToPem(input);
205
+ }
206
+ function bundleP12(options) {
207
+ const certPem = normalizeCertPem(options.certificate);
208
+ const cert = forge.pki.certificateFromPem(certPem);
209
+ const privateKey = forge.pki.privateKeyFromPem(options.privateKeyPem);
210
+ const friendlyName = options.friendlyName ?? "fastnode signing identity";
211
+ const p12Asn1 = forge.pkcs12.toPkcs12Asn1(
212
+ privateKey,
213
+ [cert],
214
+ options.password,
215
+ {
216
+ friendlyName,
217
+ generateLocalKeyId: true,
218
+ algorithm: "3des"
219
+ }
220
+ );
221
+ const der = forge.asn1.toDer(p12Asn1).getBytes();
222
+ return Buffer.from(der, "binary");
223
+ }
188
224
 
189
- export { createCertificate, downloadCertificate, findValidCertificates, generateCSR, generateRSACSR, revokeCertificate, revokeExpiredCertificates };
225
+ export { bundleP12, createCertificate, downloadCertificate, findValidCertificates, generateCSR, generateRSACSR, revokeCertificate, revokeExpiredCertificates };
190
226
  //# sourceMappingURL=index.mjs.map
191
227
  //# sourceMappingURL=index.mjs.map
@@ -1 +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"]}
1
+ {"version":3,"sources":["../../src/cert/csr.ts","../../src/cert/cert.ts","../../src/cert/p12.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","/**\n * PKCS#12 (.p12) packaging — bundles a certificate + private key into an\n * encrypted .p12 file, which is the format Apple's codesign, xcodebuild,\n * and Fastlane's cert action all expect for distribution signing.\n *\n * Uses node-forge's pkcs12.toPkcs12Asn1 which emits the legacy-compatible\n * format (3DES + RC2) that Keychain Access, iTMSTransporter, and older\n * Apple tooling accept. OpenSSL 3's default format requires the -legacy\n * flag and is not portable; node-forge sidesteps that entirely.\n */\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore — node-forge ships its own types but not ESM-friendly\nimport forge from \"node-forge\";\n\nexport interface BundleP12Options {\n /** Certificate: PEM string, or raw DER Buffer as returned by PortalClient.downloadCertificate */\n certificate: Buffer | string;\n /** PEM-encoded RSA private key (as produced by generateRSACSR) */\n privateKeyPem: string;\n /** Password used to encrypt the .p12 */\n password: string;\n /** Friendly name embedded in the bag (shown in Keychain Access) */\n friendlyName?: string;\n}\n\nfunction derBufferToPem(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 CERTIFICATE-----\\n${lines.join(\"\\n\")}\\n-----END CERTIFICATE-----\\n`;\n}\n\nfunction normalizeCertPem(input: Buffer | string): string {\n if (typeof input === \"string\") {\n if (input.includes(\"BEGIN CERTIFICATE\")) return input;\n // Raw base64 string without headers\n const b64 = input.replace(/\\s+/g, \"\");\n return derBufferToPem(Buffer.from(b64, \"base64\"));\n }\n return derBufferToPem(input);\n}\n\n/**\n * Create a PKCS#12 buffer containing the given cert + private key,\n * encrypted with `password`. Returns a Buffer suitable for writing to\n * disk or uploading as a form field.\n */\nexport function bundleP12(options: BundleP12Options): Buffer {\n const certPem = normalizeCertPem(options.certificate);\n const cert = forge.pki.certificateFromPem(certPem);\n const privateKey = forge.pki.privateKeyFromPem(options.privateKeyPem);\n\n const friendlyName = options.friendlyName ?? \"fastnode signing identity\";\n\n // node-forge picks 3DES for keys and RC2 for certs by default, which is\n // exactly what legacy Apple tooling expects. We pass friendlyName via the\n // bag attributes so Keychain Access shows a readable name.\n const p12Asn1 = forge.pkcs12.toPkcs12Asn1(\n privateKey,\n [cert],\n options.password,\n {\n friendlyName,\n generateLocalKeyId: true,\n algorithm: \"3des\",\n }\n );\n const der = forge.asn1.toDer(p12Asn1).getBytes();\n return Buffer.from(der, \"binary\");\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { A as AppStoreConnectClient, C as Certificate } from './index-D1Izm7qt.js';
1
+ import { a as AppStoreConnectClient, C as Certificate } from './index-BwwpAlk2.js';
2
2
  import { C as CertificateType } from './enums-B609j2rb.js';
3
3
 
4
4
  interface CertOptions {
@@ -1,4 +1,4 @@
1
- import { A as AppStoreConnectClient, C as Certificate } from './index-BLubSlgK.cjs';
1
+ import { a as AppStoreConnectClient, C as Certificate } from './index-CdfgEZwh.cjs';
2
2
  import { C as CertificateType } from './enums-B609j2rb.cjs';
3
3
 
4
4
  interface CertOptions {