@haex-space/vault-sdk 2.5.105 → 2.5.107

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 (53) hide show
  1. package/dist/cli/index.js +31 -28
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/cli/index.mjs +31 -28
  4. package/dist/cli/index.mjs.map +1 -1
  5. package/dist/{client-lIBgzxxo.d.mts → client-CBCjziWo.d.mts} +2 -2
  6. package/dist/{client-CvlnVzd_.d.ts → client-_FhZZse3.d.ts} +2 -2
  7. package/dist/index.d.mts +82 -7
  8. package/dist/index.d.ts +82 -7
  9. package/dist/index.js +199 -56
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs +185 -57
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/node.d.mts +1 -1
  14. package/dist/node.d.ts +1 -1
  15. package/dist/node.js +2 -2
  16. package/dist/node.js.map +1 -1
  17. package/dist/node.mjs +2 -2
  18. package/dist/node.mjs.map +1 -1
  19. package/dist/nuxt.js +6 -6
  20. package/dist/nuxt.js.map +1 -1
  21. package/dist/nuxt.mjs +6 -6
  22. package/dist/nuxt.mjs.map +1 -1
  23. package/dist/react.d.mts +2 -2
  24. package/dist/react.d.ts +2 -2
  25. package/dist/react.js +42 -56
  26. package/dist/react.js.map +1 -1
  27. package/dist/react.mjs +42 -56
  28. package/dist/react.mjs.map +1 -1
  29. package/dist/runtime/nuxt.plugin.client.d.mts +2 -2
  30. package/dist/runtime/nuxt.plugin.client.d.ts +2 -2
  31. package/dist/runtime/nuxt.plugin.client.js +39 -52
  32. package/dist/runtime/nuxt.plugin.client.js.map +1 -1
  33. package/dist/runtime/nuxt.plugin.client.mjs +39 -52
  34. package/dist/runtime/nuxt.plugin.client.mjs.map +1 -1
  35. package/dist/svelte.d.mts +2 -2
  36. package/dist/svelte.d.ts +2 -2
  37. package/dist/svelte.js +42 -56
  38. package/dist/svelte.js.map +1 -1
  39. package/dist/svelte.mjs +42 -56
  40. package/dist/svelte.mjs.map +1 -1
  41. package/dist/{types-D2qzgDja.d.mts → types-NWYbdRXr.d.mts} +44 -1
  42. package/dist/{types-D2qzgDja.d.ts → types-NWYbdRXr.d.ts} +44 -1
  43. package/dist/vite.js +4 -4
  44. package/dist/vite.js.map +1 -1
  45. package/dist/vite.mjs +4 -4
  46. package/dist/vite.mjs.map +1 -1
  47. package/dist/vue.d.mts +2 -2
  48. package/dist/vue.d.ts +2 -2
  49. package/dist/vue.js +42 -56
  50. package/dist/vue.js.map +1 -1
  51. package/dist/vue.mjs +42 -56
  52. package/dist/vue.mjs.map +1 -1
  53. package/package.json +21 -23
package/dist/cli/index.js CHANGED
@@ -60,7 +60,7 @@ function readManifest(options) {
60
60
  try {
61
61
  const packageJsonPath = path.resolve(rootDir, "package.json");
62
62
  packageJson = JSON.parse(fsSync.readFileSync(packageJsonPath, "utf-8"));
63
- } catch (pkgError) {
63
+ } catch {
64
64
  console.warn(`[@haex-space/vault-sdk] Warning: Could not read package.json`);
65
65
  }
66
66
  const name = parsed.name ?? packageJson.name;
@@ -97,7 +97,7 @@ function readManifest(options) {
97
97
  };
98
98
  console.log(`\u2713 [@haex-space/vault-sdk] Loaded ${resolvedManifestPath}`);
99
99
  return manifest;
100
- } catch (error) {
100
+ } catch {
101
101
  console.warn(
102
102
  `[@haex-space/vault-sdk] Warning: manifest.json not found at ${resolvedManifestPath}, extension info will not be available`
103
103
  );
@@ -109,7 +109,7 @@ function readManifest(options) {
109
109
  var EXTENSION_FILE_EXTENSION = ".xt";
110
110
  var ExtensionSigner = class {
111
111
  /**
112
- * Generiert ein Ed25519 Keypair
112
+ * Generates an Ed25519 keypair
113
113
  */
114
114
  static async generateKeypair() {
115
115
  const keypair = await crypto.webcrypto.subtle.generateKey(
@@ -134,7 +134,7 @@ var ExtensionSigner = class {
134
134
  };
135
135
  }
136
136
  /**
137
- * Berechnet SHA-256 Hash aller Dateien in einem Verzeichnis
137
+ * Computes SHA-256 hash of all files in a directory
138
138
  */
139
139
  static async hashDirectory(dirPath) {
140
140
  const files = await this.getAllFiles(dirPath);
@@ -153,7 +153,7 @@ var ExtensionSigner = class {
153
153
  return Buffer.from(hashBuffer);
154
154
  }
155
155
  /**
156
- * Signiert eine Extension
156
+ * Signs an extension
157
157
  */
158
158
  static async signExtension(extensionPath, privateKeyHex) {
159
159
  const privateKeyBuffer = Buffer.from(privateKeyHex, "hex");
@@ -173,7 +173,7 @@ var ExtensionSigner = class {
173
173
  const signatureBuffer = await crypto.webcrypto.subtle.sign(
174
174
  "Ed25519",
175
175
  privateKey,
176
- hash
176
+ new Uint8Array(hash)
177
177
  );
178
178
  return {
179
179
  signature: Buffer.from(signatureBuffer).toString("hex"),
@@ -182,7 +182,7 @@ var ExtensionSigner = class {
182
182
  };
183
183
  }
184
184
  /**
185
- * Packt und signiert eine Extension
185
+ * Packages and signs an extension
186
186
  */
187
187
  static async packageExtension(extensionPath, privateKeyHex, outputPath) {
188
188
  const extensionDir = getExtensionDir();
@@ -214,23 +214,10 @@ var ExtensionSigner = class {
214
214
  await fs__namespace.mkdir(tempDir, { recursive: true });
215
215
  let contentHash;
216
216
  try {
217
- const { execSync } = await import('child_process');
218
- execSync(`cp -r "${extensionPath}/"* "${tempDir}/"`, { stdio: "ignore" });
217
+ await fs__namespace.cp(extensionPath, tempDir, { recursive: true });
219
218
  const tempExtensionDir = path__namespace.join(tempDir, extensionDir);
220
219
  await fs__namespace.mkdir(tempExtensionDir, { recursive: true });
221
- const haextensionFiles = await fs__namespace.readdir(extensionDir);
222
- for (const file of haextensionFiles) {
223
- if (file === "private.key") continue;
224
- const srcPath = path__namespace.join(extensionDir, file);
225
- const destPath = path__namespace.join(tempExtensionDir, file);
226
- const stat2 = await fs__namespace.stat(srcPath);
227
- if (stat2.isFile()) {
228
- await fs__namespace.copyFile(srcPath, destPath);
229
- } else if (stat2.isDirectory()) {
230
- const { execSync: execSync2 } = await import('child_process');
231
- execSync2(`cp -r "${srcPath}" "${destPath}"`, { stdio: "ignore" });
232
- }
233
- }
220
+ await this.copyDirectory(extensionDir, tempExtensionDir, ["private.key"]);
234
221
  const tempManifestPath = path__namespace.join(tempExtensionDir, "manifest.json");
235
222
  await fs__namespace.writeFile(
236
223
  tempManifestPath,
@@ -247,8 +234,7 @@ var ExtensionSigner = class {
247
234
  if (fsSync__namespace.existsSync(migrationsSourcePath)) {
248
235
  const tempMigrationsPath = path__namespace.join(tempDir, manifest.migrationsDir);
249
236
  await fs__namespace.mkdir(path__namespace.dirname(tempMigrationsPath), { recursive: true });
250
- const { execSync: execSync2 } = await import('child_process');
251
- execSync2(`cp -r "${migrationsSourcePath}" "${tempMigrationsPath}"`, { stdio: "ignore" });
237
+ await fs__namespace.cp(migrationsSourcePath, tempMigrationsPath, { recursive: true });
252
238
  console.log(`\u2713 Migrations copied from ${migrationsSourceDir} to ${manifest.migrationsDir}`);
253
239
  } else {
254
240
  console.warn(`\u26A0 Migrations directory not found: ${migrationsSourcePath}`);
@@ -262,7 +248,7 @@ var ExtensionSigner = class {
262
248
  const signatureBuffer = await crypto.webcrypto.subtle.sign(
263
249
  "Ed25519",
264
250
  privateKey,
265
- contentHash
251
+ new Uint8Array(contentHash)
266
252
  );
267
253
  const signatureHex = Buffer.from(signatureBuffer).toString("hex");
268
254
  manifest.signature = signatureHex;
@@ -318,8 +304,8 @@ var ExtensionSigner = class {
318
304
  }
319
305
  // Helper Methods
320
306
  /**
321
- * Sortiert rekursiv die Schlüssel aller Objekte in einer Datenstruktur alphabetisch,
322
- * um einen kanonischen, deterministischen JSON-String zu erzeugen.
307
+ * Recursively sorts all object keys in a data structure alphabetically
308
+ * to produce a canonical, deterministic JSON string.
323
309
  */
324
310
  static sortObjectKeysRecursively(obj) {
325
311
  if (typeof obj !== "object" || obj === null) {
@@ -333,6 +319,23 @@ var ExtensionSigner = class {
333
319
  return result;
334
320
  }, {});
335
321
  }
322
+ /**
323
+ * Recursively copies a directory, excluding specified files
324
+ */
325
+ static async copyDirectory(src, dest, excludeFiles = []) {
326
+ const entries = await fs__namespace.readdir(src, { withFileTypes: true });
327
+ for (const entry of entries) {
328
+ if (excludeFiles.includes(entry.name)) continue;
329
+ const srcPath = path__namespace.join(src, entry.name);
330
+ const destPath = path__namespace.join(dest, entry.name);
331
+ if (entry.isDirectory()) {
332
+ await fs__namespace.mkdir(destPath, { recursive: true });
333
+ await this.copyDirectory(srcPath, destPath, excludeFiles);
334
+ } else {
335
+ await fs__namespace.copyFile(srcPath, destPath);
336
+ }
337
+ }
338
+ }
336
339
  static async getAllFiles(dirPath) {
337
340
  const entries = await fs__namespace.readdir(dirPath, { withFileTypes: true });
338
341
  const files = await Promise.all(
@@ -349,7 +352,7 @@ var ExtensionSigner = class {
349
352
  static async derivePublicKey(privateKeyBuffer) {
350
353
  const privateKey = await crypto.webcrypto.subtle.importKey(
351
354
  "pkcs8",
352
- privateKeyBuffer,
355
+ new Uint8Array(privateKeyBuffer),
353
356
  { name: "Ed25519", namedCurve: "Ed25519" },
354
357
  true,
355
358
  ["sign"]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/config.ts","../../src/manifest.ts","../../src/crypto/signing.ts","../../src/cli/index.ts"],"names":["resolve","existsSync","readFileSync","resolvePath","webcrypto","path","fs","stat","execSync","fsSync","archiver","Command","path2","fs2"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Utility to read haextension.config.json\n */\nimport { readFileSync, existsSync } from 'fs'\nimport { resolve } from 'path'\n\nexport interface HaextensionConfig {\n dev?: {\n port?: number\n host?: string\n haextension_dir?: string\n }\n keys?: {\n public_key_path?: string\n private_key_path?: string\n }\n build?: {\n distDir?: string\n /**\n * Source path for migrations directory (relative to project root).\n * If manifest.migrationsDir is set, this directory will be copied\n * to the bundle at the path specified in migrationsDir.\n * Default: \"app/{migrationsDir}\" (for Nuxt projects)\n * Example: \"app/database/migrations\" -> copies to \"database/migrations\" in bundle\n */\n migrationsSourceDir?: string\n }\n}\n\n/**\n * Read haextension.config.json from the project root\n * Returns null if file doesn't exist\n */\nexport function readHaextensionConfig(rootDir: string = process.cwd()): HaextensionConfig | null {\n const configPath = resolve(rootDir, 'haextension.config.json')\n \n if (!existsSync(configPath)) {\n return null\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8')\n return JSON.parse(content)\n } catch (error) {\n console.warn(`Failed to parse haextension.config.json: ${error}`)\n return null\n }\n}\n\n/**\n * Get extension directory from config or use default\n */\nexport function getExtensionDir(rootDir: string = process.cwd()): string {\n const config = readHaextensionConfig(rootDir)\n return config?.dev?.haextension_dir || 'haextension'\n}\n","/**\n * Utility for reading and processing extension manifest files\n */\nimport { readFileSync } from \"node:fs\";\nimport { resolve as resolvePath } from \"node:path\";\nimport type { ExtensionManifest } from \"./types\";\n\nexport interface ReadManifestOptions {\n /** Root directory of the project */\n rootDir: string;\n /** Path to manifest.json (if not provided, will use extensionDir) */\n manifestPath?: string;\n /** Directory containing extension files (default: \"haextension\") */\n extensionDir?: string;\n}\n\n/**\n * Reads and processes the extension manifest.json file\n * Falls back to package.json version if manifest doesn't specify one\n */\nexport function readManifest(options: ReadManifestOptions): ExtensionManifest | null {\n const { rootDir, manifestPath, extensionDir = \"haextension\" } = options;\n\n // Determine manifest path\n const resolvedManifestPath = manifestPath\n ? resolvePath(rootDir, manifestPath)\n : resolvePath(rootDir, extensionDir, \"manifest.json\");\n\n try {\n const manifestContent = readFileSync(resolvedManifestPath, \"utf-8\");\n const parsed: Partial<ExtensionManifest> = JSON.parse(manifestContent);\n\n // Read fallback values from package.json\n let packageJson: { name?: string; version?: string; author?: string; homepage?: string } = {};\n try {\n const packageJsonPath = resolvePath(rootDir, \"package.json\");\n packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n } catch (pkgError) {\n console.warn(`[@haex-space/vault-sdk] Warning: Could not read package.json`);\n }\n\n // Use manifest values with fallback to package.json\n const name = parsed.name ?? packageJson.name;\n const version = parsed.version ?? packageJson.version;\n const author = parsed.author ?? packageJson.author ?? null;\n const homepage = parsed.homepage ?? packageJson.homepage ?? null;\n\n if (!name) {\n console.warn(`[@haex-space/vault-sdk] Warning: No name found in manifest or package.json`);\n return null;\n }\n\n if (!version) {\n console.warn(`[@haex-space/vault-sdk] Warning: No version found in manifest or package.json`);\n return null;\n }\n\n const manifest: ExtensionManifest = {\n name,\n version,\n author,\n entry: parsed.entry ?? null,\n icon: parsed.icon ?? null,\n publicKey: parsed.publicKey ?? \"\",\n signature: parsed.signature ?? \"\",\n permissions: parsed.permissions ?? {\n database: [],\n filesystem: [],\n http: [],\n shell: [],\n },\n homepage,\n description: parsed.description ?? null,\n singleInstance: parsed.singleInstance ?? null,\n displayMode: parsed.displayMode ?? null,\n migrationsDir: parsed.migrationsDir ?? null,\n };\n\n console.log(`✓ [@haex-space/vault-sdk] Loaded ${resolvedManifestPath}`);\n return manifest;\n } catch (error) {\n console.warn(\n `[@haex-space/vault-sdk] Warning: manifest.json not found at ${resolvedManifestPath}, extension info will not be available`\n );\n return null;\n }\n}\n","// @haexhub/sdk/src/crypto/signing.ts\nimport { webcrypto } from \"crypto\";\nimport * as fs from \"fs/promises\";\nimport * as fsSync from \"fs\";\nimport * as path from \"path\";\nimport archiver from \"archiver\";\nimport { getExtensionDir, readHaextensionConfig } from \"~/config\";\nimport { readManifest } from \"~/manifest\";\n\nexport const EXTENSION_FILE_EXTENSION = \".xt\";\n\nexport class ExtensionSigner {\n /**\n * Generiert ein Ed25519 Keypair\n */\n static async generateKeypair(): Promise<{\n publicKey: string;\n privateKey: string;\n }> {\n const keypair = await webcrypto.subtle.generateKey(\n {\n name: \"Ed25519\",\n namedCurve: \"Ed25519\",\n },\n true,\n [\"sign\", \"verify\"]\n );\n\n const publicKeyBuffer = await webcrypto.subtle.exportKey(\n \"raw\",\n keypair.publicKey\n );\n const privateKeyBuffer = await webcrypto.subtle.exportKey(\n \"pkcs8\",\n keypair.privateKey\n );\n\n return {\n publicKey: Buffer.from(publicKeyBuffer).toString(\"hex\"),\n privateKey: Buffer.from(privateKeyBuffer).toString(\"hex\"),\n };\n }\n\n /**\n * Berechnet SHA-256 Hash aller Dateien in einem Verzeichnis\n */\n static async hashDirectory(dirPath: string): Promise<Buffer> {\n const files = await this.getAllFiles(dirPath);\n const sortedFiles = files.sort();\n\n console.log(`=== Files to hash (${sortedFiles.length}): ===`);\n for (const file of sortedFiles) {\n console.log(` - ${path.relative(dirPath, file)}`);\n }\n\n const contents: Buffer[] = [];\n for (const file of sortedFiles) {\n const content = await fs.readFile(file);\n contents.push(content);\n }\n\n const combined = Buffer.concat(contents);\n const hashBuffer = await webcrypto.subtle.digest(\"SHA-256\", combined);\n return Buffer.from(hashBuffer);\n }\n\n /**\n * Signiert eine Extension\n */\n static async signExtension(\n extensionPath: string,\n privateKeyHex: string\n ): Promise<{ signature: string; publicKey: string; hash: string }> {\n const privateKeyBuffer = Buffer.from(privateKeyHex, \"hex\");\n const privateKey = await webcrypto.subtle.importKey(\n \"pkcs8\",\n privateKeyBuffer,\n {\n name: \"Ed25519\",\n namedCurve: \"Ed25519\",\n },\n true,\n [\"sign\"]\n );\n\n const publicKeyBuffer = await this.derivePublicKey(privateKeyBuffer);\n const publicKeyHex = Buffer.from(publicKeyBuffer).toString(\"hex\");\n\n const hash = await this.hashDirectory(extensionPath);\n\n const signatureBuffer = await webcrypto.subtle.sign(\n \"Ed25519\",\n privateKey,\n hash\n );\n\n return {\n signature: Buffer.from(signatureBuffer).toString(\"hex\"),\n publicKey: publicKeyHex,\n hash: hash.toString(\"hex\"),\n };\n }\n\n /**\n * Packt und signiert eine Extension\n */\n static async packageExtension(\n extensionPath: string,\n privateKeyHex: string,\n outputPath?: string\n ): Promise<string> {\n // === VORBEREITUNG ===\n // Read manifest from haextension/ folder (using config)\n const extensionDir = getExtensionDir();\n const manifestPath = path.join(extensionDir, \"manifest.json\");\n const originalManifestContent = await fs.readFile(manifestPath, \"utf-8\");\n\n // Read manifest with version fallback to package.json\n const manifestObject = readManifest({\n rootDir: process.cwd(),\n extensionDir,\n });\n\n if (!manifestObject) {\n throw new Error(\"Failed to read manifest.json\");\n }\n\n const manifest = { ...manifestObject };\n\n // 1. Private Key importieren und Public Key ableiten\n const privateKeyBuffer = Buffer.from(privateKeyHex, \"hex\");\n const privateKey = await webcrypto.subtle.importKey(\n \"pkcs8\",\n privateKeyBuffer,\n { name: \"Ed25519\", namedCurve: \"Ed25519\" },\n true,\n [\"sign\"]\n );\n const publicKeyBuffer = await this.derivePublicKey(privateKeyBuffer);\n const publicKeyHex = Buffer.from(publicKeyBuffer).toString(\"hex\");\n\n // === SIGNIERUNGSPROZESS ===\n\n // 2. Manifest für die Hash-Berechnung vorbereiten\n // (Public Key rein, Signatur als leeren Platzhalter)\n manifest.publicKey = publicKeyHex;\n manifest.signature = \"\"; // signature leeren um Hash zu berechnen\n\n const canonicalManifestForHashing =\n this.sortObjectKeysRecursively(manifest);\n\n // 3. Temporäres Verzeichnis mit der exakten Struktur des Archivs erstellen\n const { tmpdir } = await import(\"os\");\n const tempDir = path.join(tmpdir(), `haex-signing-${Date.now()}`);\n await fs.mkdir(tempDir, { recursive: true });\n\n let contentHash: Buffer;\n try {\n // Kopiere extensionPath Dateien ins temp root\n const { execSync } = await import(\"child_process\");\n execSync(`cp -r \"${extensionPath}/\"* \"${tempDir}/\"`, { stdio: \"ignore\" });\n\n // Kopiere haextension Verzeichnis (ohne private.key)\n const tempExtensionDir = path.join(tempDir, extensionDir);\n await fs.mkdir(tempExtensionDir, { recursive: true });\n\n // Kopiere alle Dateien aus haextension/ außer private.key\n // (manifest.json wird danach mit leerer Signatur überschrieben)\n const haextensionFiles = await fs.readdir(extensionDir);\n for (const file of haextensionFiles) {\n if (file === 'private.key') continue;\n const srcPath = path.join(extensionDir, file);\n const destPath = path.join(tempExtensionDir, file);\n const stat = await fs.stat(srcPath);\n if (stat.isFile()) {\n await fs.copyFile(srcPath, destPath);\n } else if (stat.isDirectory()) {\n const { execSync } = await import(\"child_process\");\n execSync(`cp -r \"${srcPath}\" \"${destPath}\"`, { stdio: \"ignore\" });\n }\n }\n\n // Schreibe manifest.json mit leerer Signatur ins temp haextension Verzeichnis\n // (überschreibt die vorher kopierte Version)\n const tempManifestPath = path.join(tempExtensionDir, \"manifest.json\");\n await fs.writeFile(\n tempManifestPath,\n JSON.stringify(canonicalManifestForHashing, null, 2)\n );\n\n // Kopiere haextension.config.json wenn vorhanden\n const configPath = path.join(process.cwd(), \"haextension.config.json\");\n if (fsSync.existsSync(configPath)) {\n await fs.copyFile(configPath, path.join(tempDir, \"haextension.config.json\"));\n }\n\n // Kopiere Migrations-Verzeichnis wenn migrationsDir im Manifest angegeben ist\n if (manifest.migrationsDir) {\n const config = readHaextensionConfig(process.cwd());\n // Default: app/{migrationsDir} für Nuxt-Projekte\n const migrationsSourceDir = config?.build?.migrationsSourceDir || `app/${manifest.migrationsDir}`;\n const migrationsSourcePath = path.join(process.cwd(), migrationsSourceDir);\n\n if (fsSync.existsSync(migrationsSourcePath)) {\n const tempMigrationsPath = path.join(tempDir, manifest.migrationsDir);\n await fs.mkdir(path.dirname(tempMigrationsPath), { recursive: true });\n const { execSync } = await import(\"child_process\");\n execSync(`cp -r \"${migrationsSourcePath}\" \"${tempMigrationsPath}\"`, { stdio: \"ignore\" });\n console.log(`✓ Migrations copied from ${migrationsSourceDir} to ${manifest.migrationsDir}`);\n } else {\n console.warn(`⚠ Migrations directory not found: ${migrationsSourcePath}`);\n }\n }\n\n // Hash über das komplette temp Verzeichnis berechnen\n contentHash = await this.hashDirectory(tempDir);\n } finally {\n // Cleanup temp directory\n await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});\n }\n\n // 4. Echte Signatur aus diesem Hash erstellen\n const signatureBuffer = await webcrypto.subtle.sign(\n \"Ed25519\",\n privateKey,\n contentHash\n );\n const signatureHex = Buffer.from(signatureBuffer).toString(\"hex\");\n\n // 5. Finale manifest.json mit der echten Signatur erstellen\n manifest.signature = signatureHex;\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));\n\n // === VERPACKUNG & AUFRÄUMEN ===\n\n // 6. Das Verzeichnis zippen und haextension.config.json + haextension/ Ordner hinzufügen\n const finalOutputPath =\n outputPath || `${manifest.name}-${manifest.version}${EXTENSION_FILE_EXTENSION}`;\n const output = fsSync.createWriteStream(finalOutputPath);\n const archive = archiver(\"zip\", { zlib: { level: 9 } });\n\n return new Promise((resolve, reject) => {\n output.on(\"close\", async () => {\n // Aufräumen: Die Original-Manifest-Datei wiederherstellen\n await fs.writeFile(manifestPath, originalManifestContent);\n console.log(\"content_hash:\", contentHash);\n console.log(\n `✓ Extension packaged: ${finalOutputPath} (${archive.pointer()} bytes)`\n );\n\n // Verify the signature of the created package\n console.log(\"\\n🔍 Verifying signature...\");\n const verifyResult = await this.verifyPackage(finalOutputPath);\n if (!verifyResult.valid) {\n console.error(`❌ Signature verification failed: ${verifyResult.error}`);\n reject(new Error(`Signature verification failed: ${verifyResult.error}`));\n return;\n }\n console.log(\"✓ Signature verified successfully!\");\n\n resolve(finalOutputPath);\n });\n\n output.on(\"error\", (err) => {\n // Bei Fehler ebenfalls aufräumen\n fs.writeFile(manifestPath, originalManifestContent).finally(() =>\n reject(err)\n );\n });\n archive.on(\"error\", reject);\n\n archive.pipe(output);\n\n // Add extension files\n archive.directory(extensionPath, false);\n\n // Add haextension directory with manifest (excluding private.key)\n archive.glob(\"**/*\", {\n cwd: extensionDir,\n ignore: [\"private.key\"],\n dot: false\n }, { prefix: extensionDir });\n\n // Add haextension.config.json if it exists\n const configPath = path.join(process.cwd(), \"haextension.config.json\");\n if (fsSync.existsSync(configPath)) {\n archive.file(configPath, { name: \"haextension.config.json\" });\n }\n\n // Add migrations directory if migrationsDir is specified in manifest\n if (manifest.migrationsDir) {\n const config = readHaextensionConfig(process.cwd());\n const migrationsSourceDir = config?.build?.migrationsSourceDir || `app/${manifest.migrationsDir}`;\n const migrationsSourcePath = path.join(process.cwd(), migrationsSourceDir);\n\n if (fsSync.existsSync(migrationsSourcePath)) {\n archive.directory(migrationsSourcePath, manifest.migrationsDir);\n console.log(`✓ Adding migrations to bundle: ${manifest.migrationsDir}`);\n }\n }\n\n archive.finalize();\n });\n }\n\n // Helper Methods\n\n /**\n * Sortiert rekursiv die Schlüssel aller Objekte in einer Datenstruktur alphabetisch,\n * um einen kanonischen, deterministischen JSON-String zu erzeugen.\n */\n private static sortObjectKeysRecursively(obj: any): any {\n if (typeof obj !== \"object\" || obj === null) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.sortObjectKeysRecursively(item));\n }\n\n return Object.keys(obj)\n .sort()\n .reduce((result, key) => {\n result[key] = this.sortObjectKeysRecursively(obj[key]);\n return result;\n }, {} as { [key: string]: any });\n }\n\n private static async getAllFiles(dirPath: string): Promise<string[]> {\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n const files = await Promise.all(\n entries.map(async (entry) => {\n const fullPath = path.join(dirPath, entry.name);\n if (entry.isDirectory()) {\n return this.getAllFiles(fullPath);\n }\n return [fullPath];\n })\n );\n return files.flat();\n }\n\n private static async derivePublicKey(\n privateKeyBuffer: Buffer\n ): Promise<Uint8Array> {\n const privateKey = await webcrypto.subtle.importKey(\n \"pkcs8\",\n privateKeyBuffer,\n { name: \"Ed25519\", namedCurve: \"Ed25519\" },\n true,\n [\"sign\"]\n );\n\n const jwk = await webcrypto.subtle.exportKey(\"jwk\", privateKey);\n const publicKeyJwk = { ...jwk, d: undefined, key_ops: [\"verify\"] };\n\n const publicKey = await webcrypto.subtle.importKey(\n \"jwk\",\n publicKeyJwk,\n { name: \"Ed25519\", namedCurve: \"Ed25519\" },\n true,\n [\"verify\"]\n );\n\n return new Uint8Array(await webcrypto.subtle.exportKey(\"raw\", publicKey));\n }\n\n /**\n * Verifies the signature of a packaged extension (.xt file)\n */\n static async verifyPackage(packagePath: string): Promise<{ valid: boolean; error?: string }> {\n const JSZip = (await import(\"jszip\")).default;\n\n try {\n const zipBuffer = await fs.readFile(packagePath);\n const zip = await JSZip.loadAsync(zipBuffer);\n\n // Read manifest\n const manifestFile = zip.file(\"haextension/manifest.json\");\n if (!manifestFile) {\n return { valid: false, error: \"manifest.json not found in package\" };\n }\n const manifestContent = await manifestFile.async(\"string\");\n const manifest = JSON.parse(manifestContent);\n\n const { publicKey: publicKeyHex, signature: signatureHex } = manifest;\n\n if (!publicKeyHex || !signatureHex) {\n return { valid: false, error: \"Missing publicKey or signature in manifest\" };\n }\n\n // Collect all files from ZIP\n const files: { path: string; content: Uint8Array }[] = [];\n for (const filePath of Object.keys(zip.files)) {\n const entry = zip.files[filePath];\n if (entry && !entry.dir) {\n const content = await entry.async(\"uint8array\");\n files.push({ path: filePath, content });\n }\n }\n\n // Prepare manifest for hashing (with empty signature)\n const manifestForHashing = this.sortObjectKeysRecursively({\n ...manifest,\n signature: \"\",\n });\n const manifestBytes = new TextEncoder().encode(JSON.stringify(manifestForHashing, null, 2));\n\n // Replace manifest content with canonical version\n const filesForHashing = files.map(file => {\n if (file.path === \"haextension/manifest.json\") {\n return { path: file.path, content: manifestBytes };\n }\n return file;\n });\n\n // Sort files alphabetically (byte-order, same as hashDirectory uses .sort())\n filesForHashing.sort((a, b) => {\n if (a.path < b.path) return -1;\n if (a.path > b.path) return 1;\n return 0;\n });\n\n // Concatenate all file contents\n const totalLength = filesForHashing.reduce((sum, f) => sum + f.content.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const file of filesForHashing) {\n combined.set(file.content, offset);\n offset += file.content.length;\n }\n\n // Compute SHA-256 hash\n const hashBuffer = await webcrypto.subtle.digest(\"SHA-256\", combined);\n\n // Import public key\n const publicKeyBuffer = Buffer.from(publicKeyHex, \"hex\");\n const publicKey = await webcrypto.subtle.importKey(\n \"raw\",\n publicKeyBuffer,\n { name: \"Ed25519\", namedCurve: \"Ed25519\" },\n false,\n [\"verify\"]\n );\n\n // Verify signature\n const signatureBuffer = Buffer.from(signatureHex, \"hex\");\n const isValid = await webcrypto.subtle.verify(\n \"Ed25519\",\n publicKey,\n signatureBuffer,\n hashBuffer\n );\n\n return { valid: isValid, error: isValid ? undefined : \"Signature does not match\" };\n } catch (err) {\n return { valid: false, error: err instanceof Error ? err.message : \"Unknown error\" };\n }\n }\n}\n","#!/usr/bin/env node\n// @haexhub/sdk/src/cli/index.ts\n\nimport { Command } from \"commander\";\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { ExtensionSigner, EXTENSION_FILE_EXTENSION } from \"~/crypto/signing\";\nimport { existsSync } from \"fs\";\n\nconst program = new Command();\n\nprogram\n .name(\"haexhub\")\n .description(\"HaexHub Extension Development Tools\")\n .version(\"1.0.0\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize a new HaexHub extension in your project\")\n .option(\"-n, --name <name>\", \"Extension name\")\n .option(\"-d, --description <desc>\", \"Extension description\")\n .option(\"--author <author>\", \"Extension author\")\n .option(\"--dir <dir>\", \"Extension directory\", \"./haextension\")\n .action(async (options) => {\n try {\n const cwd = process.cwd();\n const extDir = path.resolve(cwd, options.dir);\n\n // Check if haextension directory already exists\n if (existsSync(extDir)) {\n console.error(`❌ Directory ${options.dir} already exists!`);\n process.exit(1);\n }\n\n // Read package.json if it exists\n let packageJson: any = {};\n const packageJsonPath = path.join(cwd, \"package.json\");\n if (existsSync(packageJsonPath)) {\n const content = await fs.readFile(packageJsonPath, \"utf-8\");\n packageJson = JSON.parse(content);\n }\n\n console.log(\"🚀 Initializing HaexHub Extension...\\n\");\n\n // 1. Create haextension directory\n await fs.mkdir(extDir, { recursive: true });\n console.log(`✓ Created directory: ${options.dir}`);\n\n // 2. Generate keypair\n const { publicKey, privateKey } = await ExtensionSigner.generateKeypair();\n await fs.writeFile(path.join(extDir, \"public.key\"), publicKey);\n await fs.writeFile(path.join(extDir, \"private.key\"), privateKey);\n console.log(\"✓ Generated keypair\");\n\n // 3. Create manifest.json (only required fields, optional fields come from package.json)\n const manifest: Record<string, unknown> = {\n publicKey: publicKey,\n signature: \"\",\n permissions: {\n database: [],\n filesystem: [],\n http: [],\n shell: [],\n },\n singleInstance: false,\n displayMode: \"auto\",\n };\n\n // Only add description if provided via CLI or not in package.json\n if (options.description) {\n manifest.description = options.description;\n } else if (!packageJson.description) {\n manifest.description = \"A HaexHub extension\";\n }\n\n await fs.writeFile(\n path.join(extDir, \"manifest.json\"),\n JSON.stringify(manifest, null, 2)\n );\n console.log(\"✓ Created manifest.json\");\n\n // 4. Create/update .gitignore\n const gitignorePath = path.join(cwd, \".gitignore\");\n // Remove leading ./ from dir path for gitignore\n const gitignoreDir = options.dir.replace(/^\\.\\//, '');\n const gitignoreEntries = [\n \"\\n# HaexHub Extension\",\n `${gitignoreDir}/private.key`,\n `*${EXTENSION_FILE_EXTENSION}`,\n ];\n\n if (existsSync(gitignorePath)) {\n const existing = await fs.readFile(gitignorePath, \"utf-8\");\n if (!existing.includes(`${gitignoreDir}/private.key`)) {\n await fs.appendFile(gitignorePath, gitignoreEntries.join(\"\\n\"));\n console.log(\"✓ Updated .gitignore\");\n }\n } else {\n await fs.writeFile(gitignorePath, gitignoreEntries.join(\"\\n\"));\n console.log(\"✓ Created .gitignore\");\n }\n\n // 5. Create haextension.config.json\n const config = {\n dev: {\n port: 5173,\n host: \"localhost\",\n haextension_dir: options.dir,\n },\n keys: {\n public_key_path: `${options.dir}/public.key`,\n private_key_path: `${options.dir}/private.key`,\n },\n build: {\n distDir: \"dist\",\n },\n };\n\n await fs.writeFile(\n path.join(cwd, \"haextension.config.json\"),\n JSON.stringify(config, null, 2)\n );\n console.log(\"✓ Created haextension.config.json\");\n\n // 6. Update package.json scripts\n if (existsSync(packageJsonPath)) {\n packageJson.scripts = packageJson.scripts || {};\n packageJson.scripts[\"ext:dev\"] =\n packageJson.scripts[\"ext:dev\"] || \"haexhub dev\";\n packageJson.scripts[\"ext:build\"] =\n packageJson.scripts[\"ext:build\"] ||\n `${packageJson.scripts.build || \"vite build\"} && haexhub sign dist -k ${options.dir}/private.key`;\n\n await fs.writeFile(\n packageJsonPath,\n JSON.stringify(packageJson, null, 2)\n );\n console.log(\"✓ Updated package.json scripts\");\n }\n\n console.log(\"\\n✨ Extension initialized successfully!\\n\");\n console.log(\"📝 Next steps:\");\n console.log(` 1. Edit ${options.dir}/manifest.json to configure your extension`);\n console.log(\" 2. Run 'npm run ext:dev' to start development mode\");\n console.log(\" 3. Run 'npm run ext:build' to build and sign your extension\");\n console.log(\"\\n⚠️ Important: Never commit your private key:\");\n console.log(` - ${options.dir}/private.key has been added to .gitignore`);\n console.log(\" - haextension.config.json is safe to commit (contains only paths)\\n\");\n } catch (error) {\n console.error(\"❌ Error:\", error);\n process.exit(1);\n }\n });\n\nprogram\n .command(\"keygen\")\n .description(\"Generate a new keypair for signing extensions\")\n .option(\"-o, --output <path>\", \"Output directory\", \"./haextension\")\n .action(async (options) => {\n const { publicKey, privateKey } = await ExtensionSigner.generateKeypair();\n\n const keyDir = path.resolve(options.output);\n await fs.mkdir(keyDir, { recursive: true });\n\n await fs.writeFile(path.join(keyDir, \"public.key\"), publicKey);\n await fs.writeFile(path.join(keyDir, \"private.key\"), privateKey);\n\n console.log(\"✓ Keypair generated:\");\n console.log(` Public: ${path.join(keyDir, \"public.key\")}`);\n console.log(` Private: ${path.join(keyDir, \"private.key\")}`);\n console.log(\"\\n⚠️ Keep your private key safe and never commit it!\");\n });\n\nprogram\n .command(\"sign <extension-path>\")\n .description(\"Sign and package an extension\")\n .option(\"-k, --key <path>\", \"Private key file\", \"./haextension/private.key\")\n .option(\"-o, --output <path>\", \"Output path for .haextension file\")\n .action(async (extensionPath, options) => {\n try {\n const privateKey = await fs.readFile(options.key, \"utf-8\");\n const outputPath = await ExtensionSigner.packageExtension(\n extensionPath,\n privateKey.trim(),\n options.output\n );\n console.log(`\\n✓ Extension signed and packaged: ${outputPath}`);\n } catch (error) {\n console.error(\"Error:\", error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n"]}
1
+ {"version":3,"sources":["../../src/config.ts","../../src/manifest.ts","../../src/crypto/signing.ts","../../src/cli/index.ts"],"names":["resolve","existsSync","readFileSync","resolvePath","webcrypto","path","fs","fsSync","archiver","Command","path2","fs2"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Utility to read haextension.config.json\n */\nimport { readFileSync, existsSync } from 'fs'\nimport { resolve } from 'path'\n\nexport interface HaextensionConfig {\n dev?: {\n port?: number\n host?: string\n haextension_dir?: string\n }\n keys?: {\n public_key_path?: string\n private_key_path?: string\n }\n build?: {\n distDir?: string\n /**\n * Source path for migrations directory (relative to project root).\n * If manifest.migrationsDir is set, this directory will be copied\n * to the bundle at the path specified in migrationsDir.\n * Default: \"app/{migrationsDir}\" (for Nuxt projects)\n * Example: \"app/database/migrations\" -> copies to \"database/migrations\" in bundle\n */\n migrationsSourceDir?: string\n }\n}\n\n/**\n * Read haextension.config.json from the project root\n * Returns null if file doesn't exist\n */\nexport function readHaextensionConfig(rootDir: string = process.cwd()): HaextensionConfig | null {\n const configPath = resolve(rootDir, 'haextension.config.json')\n \n if (!existsSync(configPath)) {\n return null\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8')\n return JSON.parse(content)\n } catch (error) {\n console.warn(`Failed to parse haextension.config.json: ${error}`)\n return null\n }\n}\n\n/**\n * Get extension directory from config or use default\n */\nexport function getExtensionDir(rootDir: string = process.cwd()): string {\n const config = readHaextensionConfig(rootDir)\n return config?.dev?.haextension_dir || 'haextension'\n}\n","/**\n * Utility for reading and processing extension manifest files\n */\nimport { readFileSync } from \"node:fs\";\nimport { resolve as resolvePath } from \"node:path\";\nimport type { ExtensionManifest } from \"./types\";\n\nexport interface ReadManifestOptions {\n /** Root directory of the project */\n rootDir: string;\n /** Path to manifest.json (if not provided, will use extensionDir) */\n manifestPath?: string;\n /** Directory containing extension files (default: \"haextension\") */\n extensionDir?: string;\n}\n\n/**\n * Reads and processes the extension manifest.json file\n * Falls back to package.json version if manifest doesn't specify one\n */\nexport function readManifest(options: ReadManifestOptions): ExtensionManifest | null {\n const { rootDir, manifestPath, extensionDir = \"haextension\" } = options;\n\n // Determine manifest path\n const resolvedManifestPath = manifestPath\n ? resolvePath(rootDir, manifestPath)\n : resolvePath(rootDir, extensionDir, \"manifest.json\");\n\n try {\n const manifestContent = readFileSync(resolvedManifestPath, \"utf-8\");\n const parsed: Partial<ExtensionManifest> = JSON.parse(manifestContent);\n\n // Read fallback values from package.json\n let packageJson: { name?: string; version?: string; author?: string; homepage?: string } = {};\n try {\n const packageJsonPath = resolvePath(rootDir, \"package.json\");\n packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n } catch {\n console.warn(`[@haex-space/vault-sdk] Warning: Could not read package.json`);\n }\n\n // Use manifest values with fallback to package.json\n const name = parsed.name ?? packageJson.name;\n const version = parsed.version ?? packageJson.version;\n const author = parsed.author ?? packageJson.author ?? null;\n const homepage = parsed.homepage ?? packageJson.homepage ?? null;\n\n if (!name) {\n console.warn(`[@haex-space/vault-sdk] Warning: No name found in manifest or package.json`);\n return null;\n }\n\n if (!version) {\n console.warn(`[@haex-space/vault-sdk] Warning: No version found in manifest or package.json`);\n return null;\n }\n\n const manifest: ExtensionManifest = {\n name,\n version,\n author,\n entry: parsed.entry ?? null,\n icon: parsed.icon ?? null,\n publicKey: parsed.publicKey ?? \"\",\n signature: parsed.signature ?? \"\",\n permissions: parsed.permissions ?? {\n database: [],\n filesystem: [],\n http: [],\n shell: [],\n },\n homepage,\n description: parsed.description ?? null,\n singleInstance: parsed.singleInstance ?? null,\n displayMode: parsed.displayMode ?? null,\n migrationsDir: parsed.migrationsDir ?? null,\n };\n\n console.log(`✓ [@haex-space/vault-sdk] Loaded ${resolvedManifestPath}`);\n return manifest;\n } catch {\n console.warn(\n `[@haex-space/vault-sdk] Warning: manifest.json not found at ${resolvedManifestPath}, extension info will not be available`\n );\n return null;\n }\n}\n","// @haexhub/sdk/src/crypto/signing.ts\nimport { webcrypto } from \"crypto\";\nimport * as fs from \"fs/promises\";\nimport * as fsSync from \"fs\";\nimport * as path from \"path\";\nimport archiver from \"archiver\";\nimport { getExtensionDir, readHaextensionConfig } from \"~/config\";\nimport { readManifest } from \"~/manifest\";\n\nexport const EXTENSION_FILE_EXTENSION = \".xt\";\n\nexport class ExtensionSigner {\n /**\n * Generates an Ed25519 keypair\n */\n static async generateKeypair(): Promise<{\n publicKey: string;\n privateKey: string;\n }> {\n const keypair = await webcrypto.subtle.generateKey(\n {\n name: \"Ed25519\",\n namedCurve: \"Ed25519\",\n },\n true,\n [\"sign\", \"verify\"]\n );\n\n const publicKeyBuffer = await webcrypto.subtle.exportKey(\n \"raw\",\n keypair.publicKey\n );\n const privateKeyBuffer = await webcrypto.subtle.exportKey(\n \"pkcs8\",\n keypair.privateKey\n );\n\n return {\n publicKey: Buffer.from(publicKeyBuffer).toString(\"hex\"),\n privateKey: Buffer.from(privateKeyBuffer).toString(\"hex\"),\n };\n }\n\n /**\n * Computes SHA-256 hash of all files in a directory\n */\n static async hashDirectory(dirPath: string): Promise<Buffer> {\n const files = await this.getAllFiles(dirPath);\n const sortedFiles = files.sort();\n\n console.log(`=== Files to hash (${sortedFiles.length}): ===`);\n for (const file of sortedFiles) {\n console.log(` - ${path.relative(dirPath, file)}`);\n }\n\n const contents: Buffer[] = [];\n for (const file of sortedFiles) {\n const content = await fs.readFile(file);\n contents.push(content);\n }\n\n const combined = Buffer.concat(contents);\n const hashBuffer = await webcrypto.subtle.digest(\"SHA-256\", combined);\n return Buffer.from(hashBuffer);\n }\n\n /**\n * Signs an extension\n */\n static async signExtension(\n extensionPath: string,\n privateKeyHex: string\n ): Promise<{ signature: string; publicKey: string; hash: string }> {\n const privateKeyBuffer = Buffer.from(privateKeyHex, \"hex\");\n const privateKey = await webcrypto.subtle.importKey(\n \"pkcs8\",\n privateKeyBuffer,\n {\n name: \"Ed25519\",\n namedCurve: \"Ed25519\",\n },\n true,\n [\"sign\"]\n );\n\n const publicKeyBuffer = await this.derivePublicKey(privateKeyBuffer);\n const publicKeyHex = Buffer.from(publicKeyBuffer).toString(\"hex\");\n\n const hash = await this.hashDirectory(extensionPath);\n\n const signatureBuffer = await webcrypto.subtle.sign(\n \"Ed25519\",\n privateKey,\n new Uint8Array(hash)\n );\n\n return {\n signature: Buffer.from(signatureBuffer).toString(\"hex\"),\n publicKey: publicKeyHex,\n hash: hash.toString(\"hex\"),\n };\n }\n\n /**\n * Packages and signs an extension\n */\n static async packageExtension(\n extensionPath: string,\n privateKeyHex: string,\n outputPath?: string\n ): Promise<string> {\n // === PREPARATION ===\n // Read manifest from haextension/ folder (using config)\n const extensionDir = getExtensionDir();\n const manifestPath = path.join(extensionDir, \"manifest.json\");\n const originalManifestContent = await fs.readFile(manifestPath, \"utf-8\");\n\n // Read manifest with version fallback to package.json\n const manifestObject = readManifest({\n rootDir: process.cwd(),\n extensionDir,\n });\n\n if (!manifestObject) {\n throw new Error(\"Failed to read manifest.json\");\n }\n\n const manifest = { ...manifestObject };\n\n // 1. Import private key and derive public key\n const privateKeyBuffer = Buffer.from(privateKeyHex, \"hex\");\n const privateKey = await webcrypto.subtle.importKey(\n \"pkcs8\",\n privateKeyBuffer,\n { name: \"Ed25519\", namedCurve: \"Ed25519\" },\n true,\n [\"sign\"]\n );\n const publicKeyBuffer = await this.derivePublicKey(privateKeyBuffer);\n const publicKeyHex = Buffer.from(publicKeyBuffer).toString(\"hex\");\n\n // === SIGNING PROCESS ===\n\n // 2. Prepare manifest for hash calculation\n // (add public key, set signature as empty placeholder)\n manifest.publicKey = publicKeyHex;\n manifest.signature = \"\"; // clear signature to compute hash\n\n const canonicalManifestForHashing =\n this.sortObjectKeysRecursively(manifest);\n\n // 3. Create temporary directory with exact archive structure\n const { tmpdir } = await import(\"os\");\n const tempDir = path.join(tmpdir(), `haex-signing-${Date.now()}`);\n await fs.mkdir(tempDir, { recursive: true });\n\n let contentHash: Buffer;\n try {\n // Copy extensionPath files to temp root\n await fs.cp(extensionPath, tempDir, { recursive: true });\n\n // Copy haextension directory (excluding private.key)\n const tempExtensionDir = path.join(tempDir, extensionDir);\n await fs.mkdir(tempExtensionDir, { recursive: true });\n\n // Copy all files from haextension/ except private.key\n // (manifest.json will be overwritten with empty signature afterwards)\n await this.copyDirectory(extensionDir, tempExtensionDir, ['private.key']);\n\n // Write manifest.json with empty signature to temp haextension directory\n // (overwrites the previously copied version)\n const tempManifestPath = path.join(tempExtensionDir, \"manifest.json\");\n await fs.writeFile(\n tempManifestPath,\n JSON.stringify(canonicalManifestForHashing, null, 2)\n );\n\n // Copy haextension.config.json if it exists\n const configPath = path.join(process.cwd(), \"haextension.config.json\");\n if (fsSync.existsSync(configPath)) {\n await fs.copyFile(configPath, path.join(tempDir, \"haextension.config.json\"));\n }\n\n // Copy migrations directory if migrationsDir is specified in manifest\n if (manifest.migrationsDir) {\n const config = readHaextensionConfig(process.cwd());\n // Default: app/{migrationsDir} for Nuxt projects\n const migrationsSourceDir = config?.build?.migrationsSourceDir || `app/${manifest.migrationsDir}`;\n const migrationsSourcePath = path.join(process.cwd(), migrationsSourceDir);\n\n if (fsSync.existsSync(migrationsSourcePath)) {\n const tempMigrationsPath = path.join(tempDir, manifest.migrationsDir);\n await fs.mkdir(path.dirname(tempMigrationsPath), { recursive: true });\n await fs.cp(migrationsSourcePath, tempMigrationsPath, { recursive: true });\n console.log(`✓ Migrations copied from ${migrationsSourceDir} to ${manifest.migrationsDir}`);\n } else {\n console.warn(`⚠ Migrations directory not found: ${migrationsSourcePath}`);\n }\n }\n\n // Compute hash over the complete temp directory\n contentHash = await this.hashDirectory(tempDir);\n } finally {\n // Cleanup temp directory\n await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});\n }\n\n // 4. Create actual signature from this hash\n const signatureBuffer = await webcrypto.subtle.sign(\n \"Ed25519\",\n privateKey,\n new Uint8Array(contentHash)\n );\n const signatureHex = Buffer.from(signatureBuffer).toString(\"hex\");\n\n // 5. Create final manifest.json with the actual signature\n manifest.signature = signatureHex;\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));\n\n // === PACKAGING & CLEANUP ===\n\n // 6. Zip the directory and add haextension.config.json + haextension/ folder\n const finalOutputPath =\n outputPath || `${manifest.name}-${manifest.version}${EXTENSION_FILE_EXTENSION}`;\n const output = fsSync.createWriteStream(finalOutputPath);\n const archive = archiver(\"zip\", { zlib: { level: 9 } });\n\n return new Promise((resolve, reject) => {\n output.on(\"close\", async () => {\n // Cleanup: Restore the original manifest file\n await fs.writeFile(manifestPath, originalManifestContent);\n console.log(\"content_hash:\", contentHash);\n console.log(\n `✓ Extension packaged: ${finalOutputPath} (${archive.pointer()} bytes)`\n );\n\n // Verify the signature of the created package\n console.log(\"\\n🔍 Verifying signature...\");\n const verifyResult = await this.verifyPackage(finalOutputPath);\n if (!verifyResult.valid) {\n console.error(`❌ Signature verification failed: ${verifyResult.error}`);\n reject(new Error(`Signature verification failed: ${verifyResult.error}`));\n return;\n }\n console.log(\"✓ Signature verified successfully!\");\n\n resolve(finalOutputPath);\n });\n\n output.on(\"error\", (err) => {\n // Also cleanup on error\n fs.writeFile(manifestPath, originalManifestContent).finally(() =>\n reject(err)\n );\n });\n archive.on(\"error\", reject);\n\n archive.pipe(output);\n\n // Add extension files\n archive.directory(extensionPath, false);\n\n // Add haextension directory with manifest (excluding private.key)\n archive.glob(\"**/*\", {\n cwd: extensionDir,\n ignore: [\"private.key\"],\n dot: false\n }, { prefix: extensionDir });\n\n // Add haextension.config.json if it exists\n const configPath = path.join(process.cwd(), \"haextension.config.json\");\n if (fsSync.existsSync(configPath)) {\n archive.file(configPath, { name: \"haextension.config.json\" });\n }\n\n // Add migrations directory if migrationsDir is specified in manifest\n if (manifest.migrationsDir) {\n const config = readHaextensionConfig(process.cwd());\n const migrationsSourceDir = config?.build?.migrationsSourceDir || `app/${manifest.migrationsDir}`;\n const migrationsSourcePath = path.join(process.cwd(), migrationsSourceDir);\n\n if (fsSync.existsSync(migrationsSourcePath)) {\n archive.directory(migrationsSourcePath, manifest.migrationsDir);\n console.log(`✓ Adding migrations to bundle: ${manifest.migrationsDir}`);\n }\n }\n\n archive.finalize();\n });\n }\n\n // Helper Methods\n\n /**\n * Recursively sorts all object keys in a data structure alphabetically\n * to produce a canonical, deterministic JSON string.\n */\n private static sortObjectKeysRecursively(obj: unknown): unknown {\n if (typeof obj !== \"object\" || obj === null) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.sortObjectKeysRecursively(item));\n }\n\n return Object.keys(obj as Record<string, unknown>)\n .sort()\n .reduce((result, key) => {\n result[key] = this.sortObjectKeysRecursively((obj as Record<string, unknown>)[key]);\n return result;\n }, {} as Record<string, unknown>);\n }\n\n /**\n * Recursively copies a directory, excluding specified files\n */\n private static async copyDirectory(\n src: string,\n dest: string,\n excludeFiles: string[] = []\n ): Promise<void> {\n const entries = await fs.readdir(src, { withFileTypes: true });\n for (const entry of entries) {\n if (excludeFiles.includes(entry.name)) continue;\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n if (entry.isDirectory()) {\n await fs.mkdir(destPath, { recursive: true });\n await this.copyDirectory(srcPath, destPath, excludeFiles);\n } else {\n await fs.copyFile(srcPath, destPath);\n }\n }\n }\n\n private static async getAllFiles(dirPath: string): Promise<string[]> {\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n const files = await Promise.all(\n entries.map(async (entry) => {\n const fullPath = path.join(dirPath, entry.name);\n if (entry.isDirectory()) {\n return this.getAllFiles(fullPath);\n }\n return [fullPath];\n })\n );\n return files.flat();\n }\n\n private static async derivePublicKey(\n privateKeyBuffer: Buffer\n ): Promise<Uint8Array> {\n const privateKey = await webcrypto.subtle.importKey(\n \"pkcs8\",\n new Uint8Array(privateKeyBuffer),\n { name: \"Ed25519\", namedCurve: \"Ed25519\" },\n true,\n [\"sign\"]\n );\n\n const jwk = await webcrypto.subtle.exportKey(\"jwk\", privateKey);\n const publicKeyJwk = { ...jwk, d: undefined, key_ops: [\"verify\"] };\n\n const publicKey = await webcrypto.subtle.importKey(\n \"jwk\",\n publicKeyJwk,\n { name: \"Ed25519\", namedCurve: \"Ed25519\" },\n true,\n [\"verify\"]\n );\n\n return new Uint8Array(await webcrypto.subtle.exportKey(\"raw\", publicKey));\n }\n\n /**\n * Verifies the signature of a packaged extension (.xt file)\n */\n static async verifyPackage(packagePath: string): Promise<{ valid: boolean; error?: string }> {\n const JSZip = (await import(\"jszip\")).default;\n\n try {\n const zipBuffer = await fs.readFile(packagePath);\n const zip = await JSZip.loadAsync(zipBuffer);\n\n // Read manifest\n const manifestFile = zip.file(\"haextension/manifest.json\");\n if (!manifestFile) {\n return { valid: false, error: \"manifest.json not found in package\" };\n }\n const manifestContent = await manifestFile.async(\"string\");\n const manifest = JSON.parse(manifestContent);\n\n const { publicKey: publicKeyHex, signature: signatureHex } = manifest;\n\n if (!publicKeyHex || !signatureHex) {\n return { valid: false, error: \"Missing publicKey or signature in manifest\" };\n }\n\n // Collect all files from ZIP\n const files: { path: string; content: Uint8Array }[] = [];\n for (const filePath of Object.keys(zip.files)) {\n const entry = zip.files[filePath];\n if (entry && !entry.dir) {\n const content = await entry.async(\"uint8array\");\n files.push({ path: filePath, content });\n }\n }\n\n // Prepare manifest for hashing (with empty signature)\n const manifestForHashing = this.sortObjectKeysRecursively({\n ...manifest,\n signature: \"\",\n });\n const manifestBytes = new TextEncoder().encode(JSON.stringify(manifestForHashing, null, 2));\n\n // Replace manifest content with canonical version\n const filesForHashing = files.map(file => {\n if (file.path === \"haextension/manifest.json\") {\n return { path: file.path, content: manifestBytes };\n }\n return file;\n });\n\n // Sort files alphabetically (byte-order, same as hashDirectory uses .sort())\n filesForHashing.sort((a, b) => {\n if (a.path < b.path) return -1;\n if (a.path > b.path) return 1;\n return 0;\n });\n\n // Concatenate all file contents\n const totalLength = filesForHashing.reduce((sum, f) => sum + f.content.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const file of filesForHashing) {\n combined.set(file.content, offset);\n offset += file.content.length;\n }\n\n // Compute SHA-256 hash\n const hashBuffer = await webcrypto.subtle.digest(\"SHA-256\", combined);\n\n // Import public key\n const publicKeyBuffer = Buffer.from(publicKeyHex, \"hex\");\n const publicKey = await webcrypto.subtle.importKey(\n \"raw\",\n publicKeyBuffer,\n { name: \"Ed25519\", namedCurve: \"Ed25519\" },\n false,\n [\"verify\"]\n );\n\n // Verify signature\n const signatureBuffer = Buffer.from(signatureHex, \"hex\");\n const isValid = await webcrypto.subtle.verify(\n \"Ed25519\",\n publicKey,\n signatureBuffer,\n hashBuffer\n );\n\n return { valid: isValid, error: isValid ? undefined : \"Signature does not match\" };\n } catch (err) {\n return { valid: false, error: err instanceof Error ? err.message : \"Unknown error\" };\n }\n }\n}\n","#!/usr/bin/env node\n// @haexhub/sdk/src/cli/index.ts\n\nimport { Command } from \"commander\";\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { ExtensionSigner, EXTENSION_FILE_EXTENSION } from \"~/crypto/signing\";\nimport { existsSync } from \"fs\";\n\nconst program = new Command();\n\nprogram\n .name(\"haexhub\")\n .description(\"HaexHub Extension Development Tools\")\n .version(\"1.0.0\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize a new HaexHub extension in your project\")\n .option(\"-n, --name <name>\", \"Extension name\")\n .option(\"-d, --description <desc>\", \"Extension description\")\n .option(\"--author <author>\", \"Extension author\")\n .option(\"--dir <dir>\", \"Extension directory\", \"./haextension\")\n .action(async (options) => {\n try {\n const cwd = process.cwd();\n const extDir = path.resolve(cwd, options.dir);\n\n // Check if haextension directory already exists\n if (existsSync(extDir)) {\n console.error(`❌ Directory ${options.dir} already exists!`);\n process.exit(1);\n }\n\n // Read package.json if it exists\n interface PackageJson {\n name?: string;\n description?: string;\n scripts?: Record<string, string>;\n build?: string;\n }\n let packageJson: PackageJson = {};\n const packageJsonPath = path.join(cwd, \"package.json\");\n if (existsSync(packageJsonPath)) {\n const content = await fs.readFile(packageJsonPath, \"utf-8\");\n packageJson = JSON.parse(content) as PackageJson;\n }\n\n console.log(\"🚀 Initializing HaexHub Extension...\\n\");\n\n // 1. Create haextension directory\n await fs.mkdir(extDir, { recursive: true });\n console.log(`✓ Created directory: ${options.dir}`);\n\n // 2. Generate keypair\n const { publicKey, privateKey } = await ExtensionSigner.generateKeypair();\n await fs.writeFile(path.join(extDir, \"public.key\"), publicKey);\n await fs.writeFile(path.join(extDir, \"private.key\"), privateKey);\n console.log(\"✓ Generated keypair\");\n\n // 3. Create manifest.json (only required fields, optional fields come from package.json)\n const manifest: Record<string, unknown> = {\n publicKey: publicKey,\n signature: \"\",\n permissions: {\n database: [],\n filesystem: [],\n http: [],\n shell: [],\n },\n singleInstance: false,\n displayMode: \"auto\",\n };\n\n // Only add description if provided via CLI or not in package.json\n if (options.description) {\n manifest.description = options.description;\n } else if (!packageJson.description) {\n manifest.description = \"A HaexHub extension\";\n }\n\n await fs.writeFile(\n path.join(extDir, \"manifest.json\"),\n JSON.stringify(manifest, null, 2)\n );\n console.log(\"✓ Created manifest.json\");\n\n // 4. Create/update .gitignore\n const gitignorePath = path.join(cwd, \".gitignore\");\n // Remove leading ./ from dir path for gitignore\n const gitignoreDir = options.dir.replace(/^\\.\\//, '');\n const gitignoreEntries = [\n \"\\n# HaexHub Extension\",\n `${gitignoreDir}/private.key`,\n `*${EXTENSION_FILE_EXTENSION}`,\n ];\n\n if (existsSync(gitignorePath)) {\n const existing = await fs.readFile(gitignorePath, \"utf-8\");\n if (!existing.includes(`${gitignoreDir}/private.key`)) {\n await fs.appendFile(gitignorePath, gitignoreEntries.join(\"\\n\"));\n console.log(\"✓ Updated .gitignore\");\n }\n } else {\n await fs.writeFile(gitignorePath, gitignoreEntries.join(\"\\n\"));\n console.log(\"✓ Created .gitignore\");\n }\n\n // 5. Create haextension.config.json\n const config = {\n dev: {\n port: 5173,\n host: \"localhost\",\n haextension_dir: options.dir,\n },\n keys: {\n public_key_path: `${options.dir}/public.key`,\n private_key_path: `${options.dir}/private.key`,\n },\n build: {\n distDir: \"dist\",\n },\n };\n\n await fs.writeFile(\n path.join(cwd, \"haextension.config.json\"),\n JSON.stringify(config, null, 2)\n );\n console.log(\"✓ Created haextension.config.json\");\n\n // 6. Update package.json scripts\n if (existsSync(packageJsonPath)) {\n packageJson.scripts = packageJson.scripts || {};\n packageJson.scripts[\"ext:dev\"] =\n packageJson.scripts[\"ext:dev\"] || \"haexhub dev\";\n packageJson.scripts[\"ext:build\"] =\n packageJson.scripts[\"ext:build\"] ||\n `${packageJson.scripts.build || \"vite build\"} && haexhub sign dist -k ${options.dir}/private.key`;\n\n await fs.writeFile(\n packageJsonPath,\n JSON.stringify(packageJson, null, 2)\n );\n console.log(\"✓ Updated package.json scripts\");\n }\n\n console.log(\"\\n✨ Extension initialized successfully!\\n\");\n console.log(\"📝 Next steps:\");\n console.log(` 1. Edit ${options.dir}/manifest.json to configure your extension`);\n console.log(\" 2. Run 'npm run ext:dev' to start development mode\");\n console.log(\" 3. Run 'npm run ext:build' to build and sign your extension\");\n console.log(\"\\n⚠️ Important: Never commit your private key:\");\n console.log(` - ${options.dir}/private.key has been added to .gitignore`);\n console.log(\" - haextension.config.json is safe to commit (contains only paths)\\n\");\n } catch (error) {\n console.error(\"❌ Error:\", error);\n process.exit(1);\n }\n });\n\nprogram\n .command(\"keygen\")\n .description(\"Generate a new keypair for signing extensions\")\n .option(\"-o, --output <path>\", \"Output directory\", \"./haextension\")\n .action(async (options) => {\n const { publicKey, privateKey } = await ExtensionSigner.generateKeypair();\n\n const keyDir = path.resolve(options.output);\n await fs.mkdir(keyDir, { recursive: true });\n\n await fs.writeFile(path.join(keyDir, \"public.key\"), publicKey);\n await fs.writeFile(path.join(keyDir, \"private.key\"), privateKey);\n\n console.log(\"✓ Keypair generated:\");\n console.log(` Public: ${path.join(keyDir, \"public.key\")}`);\n console.log(` Private: ${path.join(keyDir, \"private.key\")}`);\n console.log(\"\\n⚠️ Keep your private key safe and never commit it!\");\n });\n\nprogram\n .command(\"sign <extension-path>\")\n .description(\"Sign and package an extension\")\n .option(\"-k, --key <path>\", \"Private key file\", \"./haextension/private.key\")\n .option(\"-o, --output <path>\", \"Output path for .haextension file\")\n .action(async (extensionPath, options) => {\n try {\n const privateKey = await fs.readFile(options.key, \"utf-8\");\n const outputPath = await ExtensionSigner.packageExtension(\n extensionPath,\n privateKey.trim(),\n options.output\n );\n console.log(`\\n✓ Extension signed and packaged: ${outputPath}`);\n } catch (error) {\n console.error(\"Error:\", error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n"]}
@@ -35,7 +35,7 @@ function readManifest(options) {
35
35
  try {
36
36
  const packageJsonPath = resolve(rootDir, "package.json");
37
37
  packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
38
- } catch (pkgError) {
38
+ } catch {
39
39
  console.warn(`[@haex-space/vault-sdk] Warning: Could not read package.json`);
40
40
  }
41
41
  const name = parsed.name ?? packageJson.name;
@@ -72,7 +72,7 @@ function readManifest(options) {
72
72
  };
73
73
  console.log(`\u2713 [@haex-space/vault-sdk] Loaded ${resolvedManifestPath}`);
74
74
  return manifest;
75
- } catch (error) {
75
+ } catch {
76
76
  console.warn(
77
77
  `[@haex-space/vault-sdk] Warning: manifest.json not found at ${resolvedManifestPath}, extension info will not be available`
78
78
  );
@@ -84,7 +84,7 @@ function readManifest(options) {
84
84
  var EXTENSION_FILE_EXTENSION = ".xt";
85
85
  var ExtensionSigner = class {
86
86
  /**
87
- * Generiert ein Ed25519 Keypair
87
+ * Generates an Ed25519 keypair
88
88
  */
89
89
  static async generateKeypair() {
90
90
  const keypair = await webcrypto.subtle.generateKey(
@@ -109,7 +109,7 @@ var ExtensionSigner = class {
109
109
  };
110
110
  }
111
111
  /**
112
- * Berechnet SHA-256 Hash aller Dateien in einem Verzeichnis
112
+ * Computes SHA-256 hash of all files in a directory
113
113
  */
114
114
  static async hashDirectory(dirPath) {
115
115
  const files = await this.getAllFiles(dirPath);
@@ -128,7 +128,7 @@ var ExtensionSigner = class {
128
128
  return Buffer.from(hashBuffer);
129
129
  }
130
130
  /**
131
- * Signiert eine Extension
131
+ * Signs an extension
132
132
  */
133
133
  static async signExtension(extensionPath, privateKeyHex) {
134
134
  const privateKeyBuffer = Buffer.from(privateKeyHex, "hex");
@@ -148,7 +148,7 @@ var ExtensionSigner = class {
148
148
  const signatureBuffer = await webcrypto.subtle.sign(
149
149
  "Ed25519",
150
150
  privateKey,
151
- hash
151
+ new Uint8Array(hash)
152
152
  );
153
153
  return {
154
154
  signature: Buffer.from(signatureBuffer).toString("hex"),
@@ -157,7 +157,7 @@ var ExtensionSigner = class {
157
157
  };
158
158
  }
159
159
  /**
160
- * Packt und signiert eine Extension
160
+ * Packages and signs an extension
161
161
  */
162
162
  static async packageExtension(extensionPath, privateKeyHex, outputPath) {
163
163
  const extensionDir = getExtensionDir();
@@ -189,23 +189,10 @@ var ExtensionSigner = class {
189
189
  await fs.mkdir(tempDir, { recursive: true });
190
190
  let contentHash;
191
191
  try {
192
- const { execSync } = await import('child_process');
193
- execSync(`cp -r "${extensionPath}/"* "${tempDir}/"`, { stdio: "ignore" });
192
+ await fs.cp(extensionPath, tempDir, { recursive: true });
194
193
  const tempExtensionDir = path.join(tempDir, extensionDir);
195
194
  await fs.mkdir(tempExtensionDir, { recursive: true });
196
- const haextensionFiles = await fs.readdir(extensionDir);
197
- for (const file of haextensionFiles) {
198
- if (file === "private.key") continue;
199
- const srcPath = path.join(extensionDir, file);
200
- const destPath = path.join(tempExtensionDir, file);
201
- const stat2 = await fs.stat(srcPath);
202
- if (stat2.isFile()) {
203
- await fs.copyFile(srcPath, destPath);
204
- } else if (stat2.isDirectory()) {
205
- const { execSync: execSync2 } = await import('child_process');
206
- execSync2(`cp -r "${srcPath}" "${destPath}"`, { stdio: "ignore" });
207
- }
208
- }
195
+ await this.copyDirectory(extensionDir, tempExtensionDir, ["private.key"]);
209
196
  const tempManifestPath = path.join(tempExtensionDir, "manifest.json");
210
197
  await fs.writeFile(
211
198
  tempManifestPath,
@@ -222,8 +209,7 @@ var ExtensionSigner = class {
222
209
  if (fsSync.existsSync(migrationsSourcePath)) {
223
210
  const tempMigrationsPath = path.join(tempDir, manifest.migrationsDir);
224
211
  await fs.mkdir(path.dirname(tempMigrationsPath), { recursive: true });
225
- const { execSync: execSync2 } = await import('child_process');
226
- execSync2(`cp -r "${migrationsSourcePath}" "${tempMigrationsPath}"`, { stdio: "ignore" });
212
+ await fs.cp(migrationsSourcePath, tempMigrationsPath, { recursive: true });
227
213
  console.log(`\u2713 Migrations copied from ${migrationsSourceDir} to ${manifest.migrationsDir}`);
228
214
  } else {
229
215
  console.warn(`\u26A0 Migrations directory not found: ${migrationsSourcePath}`);
@@ -237,7 +223,7 @@ var ExtensionSigner = class {
237
223
  const signatureBuffer = await webcrypto.subtle.sign(
238
224
  "Ed25519",
239
225
  privateKey,
240
- contentHash
226
+ new Uint8Array(contentHash)
241
227
  );
242
228
  const signatureHex = Buffer.from(signatureBuffer).toString("hex");
243
229
  manifest.signature = signatureHex;
@@ -293,8 +279,8 @@ var ExtensionSigner = class {
293
279
  }
294
280
  // Helper Methods
295
281
  /**
296
- * Sortiert rekursiv die Schlüssel aller Objekte in einer Datenstruktur alphabetisch,
297
- * um einen kanonischen, deterministischen JSON-String zu erzeugen.
282
+ * Recursively sorts all object keys in a data structure alphabetically
283
+ * to produce a canonical, deterministic JSON string.
298
284
  */
299
285
  static sortObjectKeysRecursively(obj) {
300
286
  if (typeof obj !== "object" || obj === null) {
@@ -308,6 +294,23 @@ var ExtensionSigner = class {
308
294
  return result;
309
295
  }, {});
310
296
  }
297
+ /**
298
+ * Recursively copies a directory, excluding specified files
299
+ */
300
+ static async copyDirectory(src, dest, excludeFiles = []) {
301
+ const entries = await fs.readdir(src, { withFileTypes: true });
302
+ for (const entry of entries) {
303
+ if (excludeFiles.includes(entry.name)) continue;
304
+ const srcPath = path.join(src, entry.name);
305
+ const destPath = path.join(dest, entry.name);
306
+ if (entry.isDirectory()) {
307
+ await fs.mkdir(destPath, { recursive: true });
308
+ await this.copyDirectory(srcPath, destPath, excludeFiles);
309
+ } else {
310
+ await fs.copyFile(srcPath, destPath);
311
+ }
312
+ }
313
+ }
311
314
  static async getAllFiles(dirPath) {
312
315
  const entries = await fs.readdir(dirPath, { withFileTypes: true });
313
316
  const files = await Promise.all(
@@ -324,7 +327,7 @@ var ExtensionSigner = class {
324
327
  static async derivePublicKey(privateKeyBuffer) {
325
328
  const privateKey = await webcrypto.subtle.importKey(
326
329
  "pkcs8",
327
- privateKeyBuffer,
330
+ new Uint8Array(privateKeyBuffer),
328
331
  { name: "Ed25519", namedCurve: "Ed25519" },
329
332
  true,
330
333
  ["sign"]