@haex-space/vault-sdk 2.3.4 → 2.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  'use strict';
3
3
 
4
4
  var commander = require('commander');
5
- var fs2 = require('fs/promises');
5
+ var fs = require('fs/promises');
6
6
  var path = require('path');
7
7
  var crypto = require('crypto');
8
8
  var fsSync = require('fs');
@@ -28,7 +28,7 @@ function _interopNamespace(e) {
28
28
  return Object.freeze(n);
29
29
  }
30
30
 
31
- var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2);
31
+ var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
32
32
  var path__namespace = /*#__PURE__*/_interopNamespace(path);
33
33
  var fsSync__namespace = /*#__PURE__*/_interopNamespace(fsSync);
34
34
  var archiver__default = /*#__PURE__*/_interopDefault(archiver);
@@ -145,7 +145,7 @@ var ExtensionSigner = class {
145
145
  }
146
146
  const contents = [];
147
147
  for (const file of sortedFiles) {
148
- const content = await fs2__namespace.readFile(file);
148
+ const content = await fs__namespace.readFile(file);
149
149
  contents.push(content);
150
150
  }
151
151
  const combined = Buffer.concat(contents);
@@ -187,7 +187,7 @@ var ExtensionSigner = class {
187
187
  static async packageExtension(extensionPath, privateKeyHex, outputPath) {
188
188
  const extensionDir = getExtensionDir();
189
189
  const manifestPath = path__namespace.join(extensionDir, "manifest.json");
190
- const originalManifestContent = await fs2__namespace.readFile(manifestPath, "utf-8");
190
+ const originalManifestContent = await fs__namespace.readFile(manifestPath, "utf-8");
191
191
  const manifestObject = readManifest({
192
192
  rootDir: process.cwd(),
193
193
  extensionDir
@@ -211,25 +211,34 @@ var ExtensionSigner = class {
211
211
  const canonicalManifestForHashing = this.sortObjectKeysRecursively(manifest);
212
212
  const { tmpdir } = await import('os');
213
213
  const tempDir = path__namespace.join(tmpdir(), `haex-signing-${Date.now()}`);
214
- await fs2__namespace.mkdir(tempDir, { recursive: true });
214
+ await fs__namespace.mkdir(tempDir, { recursive: true });
215
215
  let contentHash;
216
216
  try {
217
217
  const { execSync } = await import('child_process');
218
218
  execSync(`cp -r "${extensionPath}/"* "${tempDir}/"`, { stdio: "ignore" });
219
219
  const tempExtensionDir = path__namespace.join(tempDir, extensionDir);
220
- await fs2__namespace.mkdir(tempExtensionDir, { recursive: true });
221
- const publicKeyPath = path__namespace.join(extensionDir, "public.key");
222
- if (fsSync__namespace.existsSync(publicKeyPath)) {
223
- await fs2__namespace.copyFile(publicKeyPath, path__namespace.join(tempExtensionDir, "public.key"));
220
+ 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
+ }
224
233
  }
225
234
  const tempManifestPath = path__namespace.join(tempExtensionDir, "manifest.json");
226
- await fs2__namespace.writeFile(
235
+ await fs__namespace.writeFile(
227
236
  tempManifestPath,
228
237
  JSON.stringify(canonicalManifestForHashing, null, 2)
229
238
  );
230
239
  const configPath = path__namespace.join(process.cwd(), "haextension.config.json");
231
240
  if (fsSync__namespace.existsSync(configPath)) {
232
- await fs2__namespace.copyFile(configPath, path__namespace.join(tempDir, "haextension.config.json"));
241
+ await fs__namespace.copyFile(configPath, path__namespace.join(tempDir, "haextension.config.json"));
233
242
  }
234
243
  if (manifest.migrationsDir) {
235
244
  const config = readHaextensionConfig(process.cwd());
@@ -237,7 +246,7 @@ var ExtensionSigner = class {
237
246
  const migrationsSourcePath = path__namespace.join(process.cwd(), migrationsSourceDir);
238
247
  if (fsSync__namespace.existsSync(migrationsSourcePath)) {
239
248
  const tempMigrationsPath = path__namespace.join(tempDir, manifest.migrationsDir);
240
- await fs2__namespace.mkdir(path__namespace.dirname(tempMigrationsPath), { recursive: true });
249
+ await fs__namespace.mkdir(path__namespace.dirname(tempMigrationsPath), { recursive: true });
241
250
  const { execSync: execSync2 } = await import('child_process');
242
251
  execSync2(`cp -r "${migrationsSourcePath}" "${tempMigrationsPath}"`, { stdio: "ignore" });
243
252
  console.log(`\u2713 Migrations copied from ${migrationsSourceDir} to ${manifest.migrationsDir}`);
@@ -247,7 +256,7 @@ var ExtensionSigner = class {
247
256
  }
248
257
  contentHash = await this.hashDirectory(tempDir);
249
258
  } finally {
250
- await fs2__namespace.rm(tempDir, { recursive: true, force: true }).catch(() => {
259
+ await fs__namespace.rm(tempDir, { recursive: true, force: true }).catch(() => {
251
260
  });
252
261
  }
253
262
  const signatureBuffer = await crypto.webcrypto.subtle.sign(
@@ -257,21 +266,29 @@ var ExtensionSigner = class {
257
266
  );
258
267
  const signatureHex = Buffer.from(signatureBuffer).toString("hex");
259
268
  manifest.signature = signatureHex;
260
- await fs2__namespace.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
269
+ await fs__namespace.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
261
270
  const finalOutputPath = outputPath || `${manifest.name}-${manifest.version}${EXTENSION_FILE_EXTENSION}`;
262
271
  const output = fsSync__namespace.createWriteStream(finalOutputPath);
263
272
  const archive = archiver__default.default("zip", { zlib: { level: 9 } });
264
273
  return new Promise((resolve3, reject) => {
265
274
  output.on("close", async () => {
266
- await fs2__namespace.writeFile(manifestPath, originalManifestContent);
275
+ await fs__namespace.writeFile(manifestPath, originalManifestContent);
267
276
  console.log("content_hash:", contentHash);
268
277
  console.log(
269
- `\u2713 Extension packaged!!: ${finalOutputPath} (${archive.pointer()} bytes)`
278
+ `\u2713 Extension packaged: ${finalOutputPath} (${archive.pointer()} bytes)`
270
279
  );
280
+ console.log("\n\u{1F50D} Verifying signature...");
281
+ const verifyResult = await this.verifyPackage(finalOutputPath);
282
+ if (!verifyResult.valid) {
283
+ console.error(`\u274C Signature verification failed: ${verifyResult.error}`);
284
+ reject(new Error(`Signature verification failed: ${verifyResult.error}`));
285
+ return;
286
+ }
287
+ console.log("\u2713 Signature verified successfully!");
271
288
  resolve3(finalOutputPath);
272
289
  });
273
290
  output.on("error", (err) => {
274
- fs2__namespace.writeFile(manifestPath, originalManifestContent).finally(
291
+ fs__namespace.writeFile(manifestPath, originalManifestContent).finally(
275
292
  () => reject(err)
276
293
  );
277
294
  });
@@ -317,7 +334,7 @@ var ExtensionSigner = class {
317
334
  }, {});
318
335
  }
319
336
  static async getAllFiles(dirPath) {
320
- const entries = await fs2__namespace.readdir(dirPath, { withFileTypes: true });
337
+ const entries = await fs__namespace.readdir(dirPath, { withFileTypes: true });
321
338
  const files = await Promise.all(
322
339
  entries.map(async (entry) => {
323
340
  const fullPath = path__namespace.join(dirPath, entry.name);
@@ -348,6 +365,72 @@ var ExtensionSigner = class {
348
365
  );
349
366
  return new Uint8Array(await crypto.webcrypto.subtle.exportKey("raw", publicKey));
350
367
  }
368
+ /**
369
+ * Verifies the signature of a packaged extension (.xt file)
370
+ */
371
+ static async verifyPackage(packagePath) {
372
+ const JSZip = (await import('jszip')).default;
373
+ try {
374
+ const zipBuffer = await fs__namespace.readFile(packagePath);
375
+ const zip = await JSZip.loadAsync(zipBuffer);
376
+ const manifestFile = zip.file("haextension/manifest.json");
377
+ if (!manifestFile) {
378
+ return { valid: false, error: "manifest.json not found in package" };
379
+ }
380
+ const manifestContent = await manifestFile.async("string");
381
+ const manifest = JSON.parse(manifestContent);
382
+ const { publicKey: publicKeyHex, signature: signatureHex } = manifest;
383
+ if (!publicKeyHex || !signatureHex) {
384
+ return { valid: false, error: "Missing publicKey or signature in manifest" };
385
+ }
386
+ const files = [];
387
+ for (const filePath of Object.keys(zip.files)) {
388
+ const entry = zip.files[filePath];
389
+ if (entry && !entry.dir) {
390
+ const content = await entry.async("uint8array");
391
+ files.push({ path: filePath, content });
392
+ }
393
+ }
394
+ const manifestForHashing = this.sortObjectKeysRecursively({
395
+ ...manifest,
396
+ signature: ""
397
+ });
398
+ const manifestBytes = new TextEncoder().encode(JSON.stringify(manifestForHashing, null, 2));
399
+ const filesForHashing = files.map((file) => {
400
+ if (file.path === "haextension/manifest.json") {
401
+ return { path: file.path, content: manifestBytes };
402
+ }
403
+ return file;
404
+ });
405
+ filesForHashing.sort((a, b) => a.path.localeCompare(b.path));
406
+ const totalLength = filesForHashing.reduce((sum, f) => sum + f.content.length, 0);
407
+ const combined = new Uint8Array(totalLength);
408
+ let offset = 0;
409
+ for (const file of filesForHashing) {
410
+ combined.set(file.content, offset);
411
+ offset += file.content.length;
412
+ }
413
+ const hashBuffer = await crypto.webcrypto.subtle.digest("SHA-256", combined);
414
+ const publicKeyBuffer = Buffer.from(publicKeyHex, "hex");
415
+ const publicKey = await crypto.webcrypto.subtle.importKey(
416
+ "raw",
417
+ publicKeyBuffer,
418
+ { name: "Ed25519", namedCurve: "Ed25519" },
419
+ false,
420
+ ["verify"]
421
+ );
422
+ const signatureBuffer = Buffer.from(signatureHex, "hex");
423
+ const isValid = await crypto.webcrypto.subtle.verify(
424
+ "Ed25519",
425
+ publicKey,
426
+ signatureBuffer,
427
+ hashBuffer
428
+ );
429
+ return { valid: isValid, error: isValid ? void 0 : "Signature does not match" };
430
+ } catch (err) {
431
+ return { valid: false, error: err instanceof Error ? err.message : "Unknown error" };
432
+ }
433
+ }
351
434
  };
352
435
  var program = new commander.Command();
353
436
  program.name("haexhub").description("HaexHub Extension Development Tools").version("1.0.0");
@@ -362,15 +445,15 @@ program.command("init").description("Initialize a new HaexHub extension in your
362
445
  let packageJson = {};
363
446
  const packageJsonPath = path__namespace.join(cwd, "package.json");
364
447
  if (fsSync.existsSync(packageJsonPath)) {
365
- const content = await fs2__namespace.readFile(packageJsonPath, "utf-8");
448
+ const content = await fs__namespace.readFile(packageJsonPath, "utf-8");
366
449
  packageJson = JSON.parse(content);
367
450
  }
368
451
  console.log("\u{1F680} Initializing HaexHub Extension...\n");
369
- await fs2__namespace.mkdir(extDir, { recursive: true });
452
+ await fs__namespace.mkdir(extDir, { recursive: true });
370
453
  console.log(`\u2713 Created directory: ${options.dir}`);
371
454
  const { publicKey, privateKey } = await ExtensionSigner.generateKeypair();
372
- await fs2__namespace.writeFile(path__namespace.join(extDir, "public.key"), publicKey);
373
- await fs2__namespace.writeFile(path__namespace.join(extDir, "private.key"), privateKey);
455
+ await fs__namespace.writeFile(path__namespace.join(extDir, "public.key"), publicKey);
456
+ await fs__namespace.writeFile(path__namespace.join(extDir, "private.key"), privateKey);
374
457
  console.log("\u2713 Generated keypair");
375
458
  const manifest = {
376
459
  publicKey,
@@ -389,7 +472,7 @@ program.command("init").description("Initialize a new HaexHub extension in your
389
472
  } else if (!packageJson.description) {
390
473
  manifest.description = "A HaexHub extension";
391
474
  }
392
- await fs2__namespace.writeFile(
475
+ await fs__namespace.writeFile(
393
476
  path__namespace.join(extDir, "manifest.json"),
394
477
  JSON.stringify(manifest, null, 2)
395
478
  );
@@ -402,13 +485,13 @@ program.command("init").description("Initialize a new HaexHub extension in your
402
485
  `*${EXTENSION_FILE_EXTENSION}`
403
486
  ];
404
487
  if (fsSync.existsSync(gitignorePath)) {
405
- const existing = await fs2__namespace.readFile(gitignorePath, "utf-8");
488
+ const existing = await fs__namespace.readFile(gitignorePath, "utf-8");
406
489
  if (!existing.includes(`${gitignoreDir}/private.key`)) {
407
- await fs2__namespace.appendFile(gitignorePath, gitignoreEntries.join("\n"));
490
+ await fs__namespace.appendFile(gitignorePath, gitignoreEntries.join("\n"));
408
491
  console.log("\u2713 Updated .gitignore");
409
492
  }
410
493
  } else {
411
- await fs2__namespace.writeFile(gitignorePath, gitignoreEntries.join("\n"));
494
+ await fs__namespace.writeFile(gitignorePath, gitignoreEntries.join("\n"));
412
495
  console.log("\u2713 Created .gitignore");
413
496
  }
414
497
  const config = {
@@ -425,7 +508,7 @@ program.command("init").description("Initialize a new HaexHub extension in your
425
508
  distDir: "dist"
426
509
  }
427
510
  };
428
- await fs2__namespace.writeFile(
511
+ await fs__namespace.writeFile(
429
512
  path__namespace.join(cwd, "haextension.config.json"),
430
513
  JSON.stringify(config, null, 2)
431
514
  );
@@ -434,7 +517,7 @@ program.command("init").description("Initialize a new HaexHub extension in your
434
517
  packageJson.scripts = packageJson.scripts || {};
435
518
  packageJson.scripts["ext:dev"] = packageJson.scripts["ext:dev"] || "haexhub dev";
436
519
  packageJson.scripts["ext:build"] = packageJson.scripts["ext:build"] || `${packageJson.scripts.build || "vite build"} && haexhub sign dist -k ${options.dir}/private.key`;
437
- await fs2__namespace.writeFile(
520
+ await fs__namespace.writeFile(
438
521
  packageJsonPath,
439
522
  JSON.stringify(packageJson, null, 2)
440
523
  );
@@ -456,9 +539,9 @@ program.command("init").description("Initialize a new HaexHub extension in your
456
539
  program.command("keygen").description("Generate a new keypair for signing extensions").option("-o, --output <path>", "Output directory", "./haextension").action(async (options) => {
457
540
  const { publicKey, privateKey } = await ExtensionSigner.generateKeypair();
458
541
  const keyDir = path__namespace.resolve(options.output);
459
- await fs2__namespace.mkdir(keyDir, { recursive: true });
460
- await fs2__namespace.writeFile(path__namespace.join(keyDir, "public.key"), publicKey);
461
- await fs2__namespace.writeFile(path__namespace.join(keyDir, "private.key"), privateKey);
542
+ await fs__namespace.mkdir(keyDir, { recursive: true });
543
+ await fs__namespace.writeFile(path__namespace.join(keyDir, "public.key"), publicKey);
544
+ await fs__namespace.writeFile(path__namespace.join(keyDir, "private.key"), privateKey);
462
545
  console.log("\u2713 Keypair generated:");
463
546
  console.log(` Public: ${path__namespace.join(keyDir, "public.key")}`);
464
547
  console.log(` Private: ${path__namespace.join(keyDir, "private.key")}`);
@@ -466,7 +549,7 @@ program.command("keygen").description("Generate a new keypair for signing extens
466
549
  });
467
550
  program.command("sign <extension-path>").description("Sign and package an extension").option("-k, --key <path>", "Private key file", "./haextension/private.key").option("-o, --output <path>", "Output path for .haextension file").action(async (extensionPath, options) => {
468
551
  try {
469
- const privateKey = await fs2__namespace.readFile(options.key, "utf-8");
552
+ const privateKey = await fs__namespace.readFile(options.key, "utf-8");
470
553
  const outputPath = await ExtensionSigner.packageExtension(
471
554
  extensionPath,
472
555
  privateKey.trim(),
@@ -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","fsSync","execSync","archiver","Command","path2","fs2"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCO,SAAS,qBAAA,CAAsB,OAAA,GAAkB,OAAA,CAAQ,GAAA,EAAI,EAA6B;AAC/F,EAAA,MAAM,UAAA,GAAaA,YAAA,CAAQ,OAAA,EAAS,yBAAyB,CAAA;AAE7D,EAAA,IAAI,CAACC,iBAAA,CAAW,UAAU,CAAA,EAAG;AAC3B,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAUC,mBAAA,CAAa,UAAA,EAAY,OAAO,CAAA;AAChD,IAAA,OAAO,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,EAC3B,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,yCAAA,EAA4C,KAAK,CAAA,CAAE,CAAA;AAChE,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKO,SAAS,eAAA,CAAgB,OAAA,GAAkB,OAAA,CAAQ,GAAA,EAAI,EAAW;AACvE,EAAA,MAAM,MAAA,GAAS,sBAAsB,OAAO,CAAA;AAC5C,EAAA,OAAO,MAAA,EAAQ,KAAK,eAAA,IAAmB,aAAA;AACzC;ACnCO,SAAS,aAAa,OAAA,EAAwD;AACnF,EAAA,MAAM,EAAE,OAAA,EAAS,YAAA,EAAc,YAAA,GAAe,eAAc,GAAI,OAAA;AAGhE,EAAA,MAAM,oBAAA,GAAuB,eACzBC,YAAA,CAAY,OAAA,EAAS,YAAY,CAAA,GACjCA,YAAA,CAAY,OAAA,EAAS,YAAA,EAAc,eAAe,CAAA;AAEtD,EAAA,IAAI;AACF,IAAA,MAAM,eAAA,GAAkBD,mBAAAA,CAAa,oBAAA,EAAsB,OAAO,CAAA;AAClE,IAAA,MAAM,MAAA,GAAqC,IAAA,CAAK,KAAA,CAAM,eAAe,CAAA;AAGrE,IAAA,IAAI,cAAuF,EAAC;AAC5F,IAAA,IAAI;AACF,MAAA,MAAM,eAAA,GAAkBC,YAAA,CAAY,OAAA,EAAS,cAAc,CAAA;AAC3D,MAAA,WAAA,GAAc,IAAA,CAAK,KAAA,CAAMD,mBAAAA,CAAa,eAAA,EAAiB,OAAO,CAAC,CAAA;AAAA,IACjE,SAAS,QAAA,EAAU;AACjB,MAAA,OAAA,CAAQ,KAAK,CAAA,4DAAA,CAA8D,CAAA;AAAA,IAC7E;AAGA,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,IAAQ,WAAA,CAAY,IAAA;AACxC,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,WAAA,CAAY,OAAA;AAC9C,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,IAAU,WAAA,CAAY,MAAA,IAAU,IAAA;AACtD,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,IAAY,WAAA,CAAY,QAAA,IAAY,IAAA;AAE5D,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAA,CAAQ,KAAK,CAAA,0EAAA,CAA4E,CAAA;AACzF,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,OAAA,CAAQ,KAAK,CAAA,6EAAA,CAA+E,CAAA;AAC5F,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,QAAA,GAA8B;AAAA,MAClC,IAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAA,EAAO,OAAO,KAAA,IAAS,IAAA;AAAA,MACvB,IAAA,EAAM,OAAO,IAAA,IAAQ,IAAA;AAAA,MACrB,SAAA,EAAW,OAAO,SAAA,IAAa,EAAA;AAAA,MAC/B,SAAA,EAAW,OAAO,SAAA,IAAa,EAAA;AAAA,MAC/B,WAAA,EAAa,OAAO,WAAA,IAAe;AAAA,QACjC,UAAU,EAAC;AAAA,QACX,YAAY,EAAC;AAAA,QACb,MAAM,EAAC;AAAA,QACP,OAAO;AAAC,OACV;AAAA,MACA,QAAA;AAAA,MACA,WAAA,EAAa,OAAO,WAAA,IAAe,IAAA;AAAA,MACnC,cAAA,EAAgB,OAAO,cAAA,IAAkB,IAAA;AAAA,MACzC,WAAA,EAAa,OAAO,WAAA,IAAe,IAAA;AAAA,MACnC,aAAA,EAAe,OAAO,aAAA,IAAiB;AAAA,KACzC;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,sCAAA,EAAoC,oBAAoB,CAAA,CAAE,CAAA;AACtE,IAAA,OAAO,QAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,+DAA+D,oBAAoB,CAAA,sCAAA;AAAA,KACrF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;AC7EO,IAAM,wBAAA,GAA2B,KAAA;AAEjC,IAAM,kBAAN,MAAsB;AAAA;AAAA;AAAA;AAAA,EAI3B,aAAa,eAAA,GAGV;AACD,IAAA,MAAM,OAAA,GAAU,MAAME,gBAAA,CAAU,MAAA,CAAO,WAAA;AAAA,MACrC;AAAA,QACE,IAAA,EAAM,SAAA;AAAA,QACN,UAAA,EAAY;AAAA,OACd;AAAA,MACA,IAAA;AAAA,MACA,CAAC,QAAQ,QAAQ;AAAA,KACnB;AAEA,IAAA,MAAM,eAAA,GAAkB,MAAMA,gBAAA,CAAU,MAAA,CAAO,SAAA;AAAA,MAC7C,KAAA;AAAA,MACA,OAAA,CAAQ;AAAA,KACV;AACA,IAAA,MAAM,gBAAA,GAAmB,MAAMA,gBAAA,CAAU,MAAA,CAAO,SAAA;AAAA,MAC9C,OAAA;AAAA,MACA,OAAA,CAAQ;AAAA,KACV;AAEA,IAAA,OAAO;AAAA,MACL,WAAW,MAAA,CAAO,IAAA,CAAK,eAAe,CAAA,CAAE,SAAS,KAAK,CAAA;AAAA,MACtD,YAAY,MAAA,CAAO,IAAA,CAAK,gBAAgB,CAAA,CAAE,SAAS,KAAK;AAAA,KAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,cAAc,OAAA,EAAkC;AAC3D,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,WAAA,CAAY,OAAO,CAAA;AAC5C,IAAA,MAAM,WAAA,GAAc,MAAM,IAAA,EAAK;AAE/B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,mBAAA,EAAsB,WAAA,CAAY,MAAM,CAAA,MAAA,CAAQ,CAAA;AAC5D,IAAA,KAAA,MAAW,QAAQ,WAAA,EAAa;AAC9B,MAAA,OAAA,CAAQ,IAAI,CAAA,IAAA,EAAYC,eAAA,CAAA,QAAA,CAAS,OAAA,EAAS,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,IACnD;AAEA,IAAA,MAAM,WAAqB,EAAC;AAC5B,IAAA,KAAA,MAAW,QAAQ,WAAA,EAAa;AAC9B,MAAA,MAAM,OAAA,GAAU,MAASC,cAAA,CAAA,QAAA,CAAS,IAAI,CAAA;AACtC,MAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AAAA,IACvB;AAEA,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAA;AACvC,IAAA,MAAM,aAAa,MAAMF,gBAAA,CAAU,MAAA,CAAO,MAAA,CAAO,WAAW,QAAQ,CAAA;AACpE,IAAA,OAAO,MAAA,CAAO,KAAK,UAAU,CAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,aAAA,CACX,aAAA,EACA,aAAA,EACiE;AACjE,IAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,IAAA,CAAK,aAAA,EAAe,KAAK,CAAA;AACzD,IAAA,MAAM,UAAA,GAAa,MAAMA,gBAAA,CAAU,MAAA,CAAO,SAAA;AAAA,MACxC,OAAA;AAAA,MACA,gBAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,SAAA;AAAA,QACN,UAAA,EAAY;AAAA,OACd;AAAA,MACA,IAAA;AAAA,MACA,CAAC,MAAM;AAAA,KACT;AAEA,IAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,CAAK,eAAA,CAAgB,gBAAgB,CAAA;AACnE,IAAA,MAAM,eAAe,MAAA,CAAO,IAAA,CAAK,eAAe,CAAA,CAAE,SAAS,KAAK,CAAA;AAEhE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,aAAA,CAAc,aAAa,CAAA;AAEnD,IAAA,MAAM,eAAA,GAAkB,MAAMA,gBAAA,CAAU,MAAA,CAAO,IAAA;AAAA,MAC7C,SAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO;AAAA,MACL,WAAW,MAAA,CAAO,IAAA,CAAK,eAAe,CAAA,CAAE,SAAS,KAAK,CAAA;AAAA,MACtD,SAAA,EAAW,YAAA;AAAA,MACX,IAAA,EAAM,IAAA,CAAK,QAAA,CAAS,KAAK;AAAA,KAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,gBAAA,CACX,aAAA,EACA,aAAA,EACA,UAAA,EACiB;AAGjB,IAAA,MAAM,eAAe,eAAA,EAAgB;AACrC,IAAA,MAAM,YAAA,GAAoBC,eAAA,CAAA,IAAA,CAAK,YAAA,EAAc,eAAe,CAAA;AAC5D,IAAA,MAAM,uBAAA,GAA0B,MAASC,cAAA,CAAA,QAAA,CAAS,YAAA,EAAc,OAAO,CAAA;AAGvE,IAAA,MAAM,iBAAiB,YAAA,CAAa;AAAA,MAClC,OAAA,EAAS,QAAQ,GAAA,EAAI;AAAA,MACrB;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,MAAA,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAAA,IAChD;AAEA,IAAA,MAAM,QAAA,GAAW,EAAE,GAAG,cAAA,EAAe;AAGrC,IAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,IAAA,CAAK,aAAA,EAAe,KAAK,CAAA;AACzD,IAAA,MAAM,UAAA,GAAa,MAAMF,gBAAA,CAAU,MAAA,CAAO,SAAA;AAAA,MACxC,OAAA;AAAA,MACA,gBAAA;AAAA,MACA,EAAE,IAAA,EAAM,SAAA,EAAW,UAAA,EAAY,SAAA,EAAU;AAAA,MACzC,IAAA;AAAA,MACA,CAAC,MAAM;AAAA,KACT;AACA,IAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,CAAK,eAAA,CAAgB,gBAAgB,CAAA;AACnE,IAAA,MAAM,eAAe,MAAA,CAAO,IAAA,CAAK,eAAe,CAAA,CAAE,SAAS,KAAK,CAAA;AAMhE,IAAA,QAAA,CAAS,SAAA,GAAY,YAAA;AACrB,IAAA,QAAA,CAAS,SAAA,GAAY,EAAA;AAErB,IAAA,MAAM,2BAAA,GACJ,IAAA,CAAK,yBAAA,CAA0B,QAAQ,CAAA;AAGzC,IAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,OAAO,IAAI,CAAA;AACpC,IAAA,MAAM,OAAA,GAAeC,qBAAK,MAAA,EAAO,EAAG,gBAAgB,IAAA,CAAK,GAAA,EAAK,CAAA,CAAE,CAAA;AAChE,IAAA,MAASC,cAAA,CAAA,KAAA,CAAM,OAAA,EAAS,EAAE,SAAA,EAAW,MAAM,CAAA;AAE3C,IAAA,IAAI,WAAA;AACJ,IAAA,IAAI;AAEF,MAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,OAAO,eAAe,CAAA;AACjD,MAAA,QAAA,CAAS,CAAA,OAAA,EAAU,aAAa,CAAA,KAAA,EAAQ,OAAO,MAAM,EAAE,KAAA,EAAO,UAAU,CAAA;AAGxE,MAAA,MAAM,gBAAA,GAAwBD,eAAA,CAAA,IAAA,CAAK,OAAA,EAAS,YAAY,CAAA;AACxD,MAAA,MAASC,cAAA,CAAA,KAAA,CAAM,gBAAA,EAAkB,EAAE,SAAA,EAAW,MAAM,CAAA;AAGpD,MAAA,MAAM,aAAA,GAAqBD,eAAA,CAAA,IAAA,CAAK,YAAA,EAAc,YAAY,CAAA;AAC1D,MAAA,IAAWE,iBAAA,CAAA,UAAA,CAAW,aAAa,CAAA,EAAG;AACpC,QAAA,MAASD,cAAA,CAAA,QAAA,CAAS,aAAA,EAAoBD,eAAA,CAAA,IAAA,CAAK,gBAAA,EAAkB,YAAY,CAAC,CAAA;AAAA,MAC5E;AAGA,MAAA,MAAM,gBAAA,GAAwBA,eAAA,CAAA,IAAA,CAAK,gBAAA,EAAkB,eAAe,CAAA;AACpE,MAAA,MAASC,cAAA,CAAA,SAAA;AAAA,QACP,gBAAA;AAAA,QACA,IAAA,CAAK,SAAA,CAAU,2BAAA,EAA6B,IAAA,EAAM,CAAC;AAAA,OACrD;AAGA,MAAA,MAAM,UAAA,GAAkBD,eAAA,CAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,yBAAyB,CAAA;AACrE,MAAA,IAAWE,iBAAA,CAAA,UAAA,CAAW,UAAU,CAAA,EAAG;AACjC,QAAA,MAASD,cAAA,CAAA,QAAA,CAAS,UAAA,EAAiBD,eAAA,CAAA,IAAA,CAAK,OAAA,EAAS,yBAAyB,CAAC,CAAA;AAAA,MAC7E;AAGA,MAAA,IAAI,SAAS,aAAA,EAAe;AAC1B,QAAA,MAAM,MAAA,GAAS,qBAAA,CAAsB,OAAA,CAAQ,GAAA,EAAK,CAAA;AAElD,QAAA,MAAM,sBAAsB,MAAA,EAAQ,KAAA,EAAO,mBAAA,IAAuB,CAAA,IAAA,EAAO,SAAS,aAAa,CAAA,CAAA;AAC/F,QAAA,MAAM,oBAAA,GAA4BA,eAAA,CAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,mBAAmB,CAAA;AAEzE,QAAA,IAAWE,iBAAA,CAAA,UAAA,CAAW,oBAAoB,CAAA,EAAG;AAC3C,UAAA,MAAM,kBAAA,GAA0BF,eAAA,CAAA,IAAA,CAAK,OAAA,EAAS,QAAA,CAAS,aAAa,CAAA;AACpE,UAAA,MAASC,qBAAWD,eAAA,CAAA,OAAA,CAAQ,kBAAkB,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACpE,UAAA,MAAM,EAAE,QAAA,EAAAG,SAAAA,EAAS,GAAI,MAAM,OAAO,eAAe,CAAA;AACjD,UAAAA,SAAAA,CAAS,UAAU,oBAAoB,CAAA,GAAA,EAAM,kBAAkB,CAAA,CAAA,CAAA,EAAK,EAAE,KAAA,EAAO,QAAA,EAAU,CAAA;AACvF,UAAA,OAAA,CAAQ,IAAI,CAAA,8BAAA,EAA4B,mBAAmB,CAAA,IAAA,EAAO,QAAA,CAAS,aAAa,CAAA,CAAE,CAAA;AAAA,QAC5F,CAAA,MAAO;AACL,UAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,uCAAA,EAAqC,oBAAoB,CAAA,CAAE,CAAA;AAAA,QAC1E;AAAA,MACF;AAGA,MAAA,WAAA,GAAc,MAAM,IAAA,CAAK,aAAA,CAAc,OAAO,CAAA;AAAA,IAChD,CAAA,SAAE;AAEA,MAAA,MAASF,cAAA,CAAA,EAAA,CAAG,OAAA,EAAS,EAAE,SAAA,EAAW,IAAA,EAAM,OAAO,IAAA,EAAM,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACvE;AAGA,IAAA,MAAM,eAAA,GAAkB,MAAMF,gBAAA,CAAU,MAAA,CAAO,IAAA;AAAA,MAC7C,SAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,MAAM,eAAe,MAAA,CAAO,IAAA,CAAK,eAAe,CAAA,CAAE,SAAS,KAAK,CAAA;AAGhE,IAAA,QAAA,CAAS,SAAA,GAAY,YAAA;AACrB,IAAA,MAASE,yBAAU,YAAA,EAAc,IAAA,CAAK,UAAU,QAAA,EAAU,IAAA,EAAM,CAAC,CAAC,CAAA;AAKlE,IAAA,MAAM,eAAA,GACJ,cAAc,CAAA,EAAG,QAAA,CAAS,IAAI,CAAA,CAAA,EAAI,QAAA,CAAS,OAAO,CAAA,EAAG,wBAAwB,CAAA,CAAA;AAC/E,IAAA,MAAM,MAAA,GAAgBC,oCAAkB,eAAe,CAAA;AACvD,IAAA,MAAM,OAAA,GAAUE,0BAAS,KAAA,EAAO,EAAE,MAAM,EAAE,KAAA,EAAO,CAAA,EAAE,EAAG,CAAA;AAEtD,IAAA,OAAO,IAAI,OAAA,CAAQ,CAACT,QAAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAA,CAAO,EAAA,CAAG,SAAS,YAAY;AAE7B,QAAA,MAASM,cAAA,CAAA,SAAA,CAAU,cAAc,uBAAuB,CAAA;AACxD,QAAA,OAAA,CAAQ,GAAA,CAAI,iBAAiB,WAAW,CAAA;AACxC,QAAA,OAAA,CAAQ,GAAA;AAAA,UACN,CAAA,6BAAA,EAA2B,eAAe,CAAA,EAAA,EAAK,OAAA,CAAQ,SAAS,CAAA,OAAA;AAAA,SAClE;AACA,QAAAN,SAAQ,eAAe,CAAA;AAAA,MACzB,CAAC,CAAA;AAED,MAAA,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AAE1B,QAAGM,cAAA,CAAA,SAAA,CAAU,YAAA,EAAc,uBAAuB,CAAA,CAAE,OAAA;AAAA,UAAQ,MAC1D,OAAO,GAAG;AAAA,SACZ;AAAA,MACF,CAAC,CAAA;AACD,MAAA,OAAA,CAAQ,EAAA,CAAG,SAAS,MAAM,CAAA;AAE1B,MAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AAGnB,MAAA,OAAA,CAAQ,SAAA,CAAU,eAAe,KAAK,CAAA;AAGtC,MAAA,OAAA,CAAQ,KAAK,MAAA,EAAQ;AAAA,QACnB,GAAA,EAAK,YAAA;AAAA,QACL,MAAA,EAAQ,CAAC,aAAa,CAAA;AAAA,QACtB,GAAA,EAAK;AAAA,OACP,EAAG,EAAE,MAAA,EAAQ,YAAA,EAAc,CAAA;AAG3B,MAAA,MAAM,UAAA,GAAkBD,eAAA,CAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,yBAAyB,CAAA;AACrE,MAAA,IAAWE,iBAAA,CAAA,UAAA,CAAW,UAAU,CAAA,EAAG;AACjC,QAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,EAAY,EAAE,IAAA,EAAM,2BAA2B,CAAA;AAAA,MAC9D;AAGA,MAAA,IAAI,SAAS,aAAA,EAAe;AAC1B,QAAA,MAAM,MAAA,GAAS,qBAAA,CAAsB,OAAA,CAAQ,GAAA,EAAK,CAAA;AAClD,QAAA,MAAM,sBAAsB,MAAA,EAAQ,KAAA,EAAO,mBAAA,IAAuB,CAAA,IAAA,EAAO,SAAS,aAAa,CAAA,CAAA;AAC/F,QAAA,MAAM,oBAAA,GAA4BF,eAAA,CAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,mBAAmB,CAAA;AAEzE,QAAA,IAAWE,iBAAA,CAAA,UAAA,CAAW,oBAAoB,CAAA,EAAG;AAC3C,UAAA,OAAA,CAAQ,SAAA,CAAU,oBAAA,EAAsB,QAAA,CAAS,aAAa,CAAA;AAC9D,UAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,oCAAA,EAAkC,QAAA,CAAS,aAAa,CAAA,CAAE,CAAA;AAAA,QACxE;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,QAAA,EAAS;AAAA,IACnB,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAe,0BAA0B,GAAA,EAAe;AACtD,IAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,IAAA,EAAM;AAC3C,MAAA,OAAO,GAAA;AAAA,IACT;AAEA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AACtB,MAAA,OAAO,IAAI,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,yBAAA,CAA0B,IAAI,CAAC,CAAA;AAAA,IAC/D;AAEA,IAAA,OAAO,MAAA,CAAO,KAAK,GAAG,CAAA,CACnB,MAAK,CACL,MAAA,CAAO,CAAC,MAAA,EAAQ,GAAA,KAAQ;AACvB,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,IAAA,CAAK,yBAAA,CAA0B,GAAA,CAAI,GAAG,CAAC,CAAA;AACrD,MAAA,OAAO,MAAA;AAAA,IACT,CAAA,EAAG,EAA4B,CAAA;AAAA,EACnC;AAAA,EAEA,aAAqB,YAAY,OAAA,EAAoC;AACnE,IAAA,MAAM,UAAU,MAASD,cAAA,CAAA,OAAA,CAAQ,SAAS,EAAE,aAAA,EAAe,MAAM,CAAA;AACjE,IAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,GAAA;AAAA,MAC1B,OAAA,CAAQ,GAAA,CAAI,OAAO,KAAA,KAAU;AAC3B,QAAA,MAAM,QAAA,GAAgBD,eAAA,CAAA,IAAA,CAAK,OAAA,EAAS,KAAA,CAAM,IAAI,CAAA;AAC9C,QAAA,IAAI,KAAA,CAAM,aAAY,EAAG;AACvB,UAAA,OAAO,IAAA,CAAK,YAAY,QAAQ,CAAA;AAAA,QAClC;AACA,QAAA,OAAO,CAAC,QAAQ,CAAA;AAAA,MAClB,CAAC;AAAA,KACH;AACA,IAAA,OAAO,MAAM,IAAA,EAAK;AAAA,EACpB;AAAA,EAEA,aAAqB,gBACnB,gBAAA,EACqB;AACrB,IAAA,MAAM,UAAA,GAAa,MAAMD,gBAAA,CAAU,MAAA,CAAO,SAAA;AAAA,MACxC,OAAA;AAAA,MACA,gBAAA;AAAA,MACA,EAAE,IAAA,EAAM,SAAA,EAAW,UAAA,EAAY,SAAA,EAAU;AAAA,MACzC,IAAA;AAAA,MACA,CAAC,MAAM;AAAA,KACT;AAEA,IAAA,MAAM,MAAM,MAAMA,gBAAA,CAAU,MAAA,CAAO,SAAA,CAAU,OAAO,UAAU,CAAA;AAC9D,IAAA,MAAM,YAAA,GAAe,EAAE,GAAG,GAAA,EAAK,GAAG,MAAA,EAAW,OAAA,EAAS,CAAC,QAAQ,CAAA,EAAE;AAEjE,IAAA,MAAM,SAAA,GAAY,MAAMA,gBAAA,CAAU,MAAA,CAAO,SAAA;AAAA,MACvC,KAAA;AAAA,MACA,YAAA;AAAA,MACA,EAAE,IAAA,EAAM,SAAA,EAAW,UAAA,EAAY,SAAA,EAAU;AAAA,MACzC,IAAA;AAAA,MACA,CAAC,QAAQ;AAAA,KACX;AAEA,IAAA,OAAO,IAAI,WAAW,MAAMA,gBAAA,CAAU,OAAO,SAAA,CAAU,KAAA,EAAO,SAAS,CAAC,CAAA;AAAA,EAC1E;AACF,CAAA;AC/UA,IAAM,OAAA,GAAU,IAAIM,iBAAA,EAAQ;AAE5B,OAAA,CACG,KAAK,SAAS,CAAA,CACd,YAAY,qCAAqC,CAAA,CACjD,QAAQ,OAAO,CAAA;AAElB,OAAA,CACG,OAAA,CAAQ,MAAM,CAAA,CACd,WAAA,CAAY,oDAAoD,EAChE,MAAA,CAAO,mBAAA,EAAqB,gBAAgB,CAAA,CAC5C,MAAA,CAAO,0BAAA,EAA4B,uBAAuB,CAAA,CAC1D,MAAA,CAAO,mBAAA,EAAqB,kBAAkB,CAAA,CAC9C,MAAA,CAAO,aAAA,EAAe,qBAAA,EAAuB,eAAe,CAAA,CAC5D,MAAA,CAAO,OAAO,OAAA,KAAY;AACzB,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,EAAI;AACxB,IAAA,MAAM,MAAA,GAAcC,eAAA,CAAA,OAAA,CAAQ,GAAA,EAAK,OAAA,CAAQ,GAAG,CAAA;AAG5C,IAAA,IAAIV,iBAAAA,CAAW,MAAM,CAAA,EAAG;AACtB,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,iBAAA,EAAe,OAAA,CAAQ,GAAG,CAAA,gBAAA,CAAkB,CAAA;AAC1D,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAGA,IAAA,IAAI,cAAmB,EAAC;AACxB,IAAA,MAAM,eAAA,GAAuBU,eAAA,CAAA,IAAA,CAAK,GAAA,EAAK,cAAc,CAAA;AACrD,IAAA,IAAIV,iBAAAA,CAAW,eAAe,CAAA,EAAG;AAC/B,MAAA,MAAM,OAAA,GAAU,MAASW,cAAA,CAAA,QAAA,CAAS,eAAA,EAAiB,OAAO,CAAA;AAC1D,MAAA,WAAA,GAAc,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IAClC;AAEA,IAAA,OAAA,CAAQ,IAAI,+CAAwC,CAAA;AAGpD,IAAA,MAASA,cAAA,CAAA,KAAA,CAAM,MAAA,EAAQ,EAAE,SAAA,EAAW,MAAM,CAAA;AAC1C,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,0BAAA,EAAwB,OAAA,CAAQ,GAAG,CAAA,CAAE,CAAA;AAGjD,IAAA,MAAM,EAAE,SAAA,EAAW,UAAA,EAAW,GAAI,MAAM,gBAAgB,eAAA,EAAgB;AACxE,IAAA,MAASA,cAAA,CAAA,SAAA,CAAeD,eAAA,CAAA,IAAA,CAAK,MAAA,EAAQ,YAAY,GAAG,SAAS,CAAA;AAC7D,IAAA,MAASC,cAAA,CAAA,SAAA,CAAeD,eAAA,CAAA,IAAA,CAAK,MAAA,EAAQ,aAAa,GAAG,UAAU,CAAA;AAC/D,IAAA,OAAA,CAAQ,IAAI,0BAAqB,CAAA;AAGjC,IAAA,MAAM,QAAA,GAAoC;AAAA,MACxC,SAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,MACX,WAAA,EAAa;AAAA,QACX,UAAU,EAAC;AAAA,QACX,YAAY,EAAC;AAAA,QACb,MAAM,EAAC;AAAA,QACP,OAAO;AAAC,OACV;AAAA,MACA,cAAA,EAAgB,KAAA;AAAA,MAChB,WAAA,EAAa;AAAA,KACf;AAGA,IAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,MAAA,QAAA,CAAS,cAAc,OAAA,CAAQ,WAAA;AAAA,IACjC,CAAA,MAAA,IAAW,CAAC,WAAA,CAAY,WAAA,EAAa;AACnC,MAAA,QAAA,CAAS,WAAA,GAAc,qBAAA;AAAA,IACzB;AAEA,IAAA,MAASC,cAAA,CAAA,SAAA;AAAA,MACFD,eAAA,CAAA,IAAA,CAAK,QAAQ,eAAe,CAAA;AAAA,MACjC,IAAA,CAAK,SAAA,CAAU,QAAA,EAAU,IAAA,EAAM,CAAC;AAAA,KAClC;AACA,IAAA,OAAA,CAAQ,IAAI,8BAAyB,CAAA;AAGrC,IAAA,MAAM,aAAA,GAAqBA,eAAA,CAAA,IAAA,CAAK,GAAA,EAAK,YAAY,CAAA;AAEjD,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,SAAS,EAAE,CAAA;AACpD,IAAA,MAAM,gBAAA,GAAmB;AAAA,MACvB,uBAAA;AAAA,MACA,GAAG,YAAY,CAAA,YAAA,CAAA;AAAA,MACf,IAAI,wBAAwB,CAAA;AAAA,KAC9B;AAEA,IAAA,IAAIV,iBAAAA,CAAW,aAAa,CAAA,EAAG;AAC7B,MAAA,MAAM,QAAA,GAAW,MAASW,cAAA,CAAA,QAAA,CAAS,aAAA,EAAe,OAAO,CAAA;AACzD,MAAA,IAAI,CAAC,QAAA,CAAS,QAAA,CAAS,CAAA,EAAG,YAAY,cAAc,CAAA,EAAG;AACrD,QAAA,MAASA,cAAA,CAAA,UAAA,CAAW,aAAA,EAAe,gBAAA,CAAiB,IAAA,CAAK,IAAI,CAAC,CAAA;AAC9D,QAAA,OAAA,CAAQ,IAAI,2BAAsB,CAAA;AAAA,MACpC;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAASA,cAAA,CAAA,SAAA,CAAU,aAAA,EAAe,gBAAA,CAAiB,IAAA,CAAK,IAAI,CAAC,CAAA;AAC7D,MAAA,OAAA,CAAQ,IAAI,2BAAsB,CAAA;AAAA,IACpC;AAGA,IAAA,MAAM,MAAA,GAAS;AAAA,MACb,GAAA,EAAK;AAAA,QACH,IAAA,EAAM,IAAA;AAAA,QACN,IAAA,EAAM,WAAA;AAAA,QACN,iBAAiB,OAAA,CAAQ;AAAA,OAC3B;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,eAAA,EAAiB,CAAA,EAAG,OAAA,CAAQ,GAAG,CAAA,WAAA,CAAA;AAAA,QAC/B,gBAAA,EAAkB,CAAA,EAAG,OAAA,CAAQ,GAAG,CAAA,YAAA;AAAA,OAClC;AAAA,MACA,KAAA,EAAO;AAAA,QACL,OAAA,EAAS;AAAA;AACX,KACF;AAEA,IAAA,MAASA,cAAA,CAAA,SAAA;AAAA,MACFD,eAAA,CAAA,IAAA,CAAK,KAAK,yBAAyB,CAAA;AAAA,MACxC,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ,IAAA,EAAM,CAAC;AAAA,KAChC;AACA,IAAA,OAAA,CAAQ,IAAI,wCAAmC,CAAA;AAG/C,IAAA,IAAIV,iBAAAA,CAAW,eAAe,CAAA,EAAG;AAC/B,MAAA,WAAA,CAAY,OAAA,GAAU,WAAA,CAAY,OAAA,IAAW,EAAC;AAC9C,MAAA,WAAA,CAAY,QAAQ,SAAS,CAAA,GAC3B,WAAA,CAAY,OAAA,CAAQ,SAAS,CAAA,IAAK,aAAA;AACpC,MAAA,WAAA,CAAY,OAAA,CAAQ,WAAW,CAAA,GAC7B,WAAA,CAAY,QAAQ,WAAW,CAAA,IAC/B,CAAA,EAAG,WAAA,CAAY,OAAA,CAAQ,KAAA,IAAS,YAAY,CAAA,yBAAA,EAA4B,QAAQ,GAAG,CAAA,YAAA,CAAA;AAErF,MAAA,MAASW,cAAA,CAAA,SAAA;AAAA,QACP,eAAA;AAAA,QACA,IAAA,CAAK,SAAA,CAAU,WAAA,EAAa,IAAA,EAAM,CAAC;AAAA,OACrC;AACA,MAAA,OAAA,CAAQ,IAAI,qCAAgC,CAAA;AAAA,IAC9C;AAEA,IAAA,OAAA,CAAQ,IAAI,gDAA2C,CAAA;AACvD,IAAA,OAAA,CAAQ,IAAI,uBAAgB,CAAA;AAC5B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,UAAA,EAAa,OAAA,CAAQ,GAAG,CAAA,0CAAA,CAA4C,CAAA;AAChF,IAAA,OAAA,CAAQ,IAAI,sDAAsD,CAAA;AAClE,IAAA,OAAA,CAAQ,IAAI,+DAA+D,CAAA;AAC3E,IAAA,OAAA,CAAQ,IAAI,2DAAiD,CAAA;AAC7D,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,KAAA,EAAQ,OAAA,CAAQ,GAAG,CAAA,yCAAA,CAA2C,CAAA;AAC1E,IAAA,OAAA,CAAQ,IAAI,wEAAwE,CAAA;AAAA,EACtF,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,iBAAY,KAAK,CAAA;AAC/B,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAEH,OAAA,CACG,OAAA,CAAQ,QAAQ,CAAA,CAChB,WAAA,CAAY,+CAA+C,CAAA,CAC3D,MAAA,CAAO,qBAAA,EAAuB,kBAAA,EAAoB,eAAe,CAAA,CACjE,MAAA,CAAO,OAAO,OAAA,KAAY;AACzB,EAAA,MAAM,EAAE,SAAA,EAAW,UAAA,EAAW,GAAI,MAAM,gBAAgB,eAAA,EAAgB;AAExE,EAAA,MAAM,MAAA,GAAcD,eAAA,CAAA,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA;AAC1C,EAAA,MAASC,cAAA,CAAA,KAAA,CAAM,MAAA,EAAQ,EAAE,SAAA,EAAW,MAAM,CAAA;AAE1C,EAAA,MAASA,cAAA,CAAA,SAAA,CAAeD,eAAA,CAAA,IAAA,CAAK,MAAA,EAAQ,YAAY,GAAG,SAAS,CAAA;AAC7D,EAAA,MAASC,cAAA,CAAA,SAAA,CAAeD,eAAA,CAAA,IAAA,CAAK,MAAA,EAAQ,aAAa,GAAG,UAAU,CAAA;AAE/D,EAAA,OAAA,CAAQ,IAAI,2BAAsB,CAAA;AAClC,EAAA,OAAA,CAAQ,IAAI,CAAA,WAAA,EAAmBA,eAAA,CAAA,IAAA,CAAK,MAAA,EAAQ,YAAY,CAAC,CAAA,CAAE,CAAA;AAC3D,EAAA,OAAA,CAAQ,IAAI,CAAA,WAAA,EAAmBA,eAAA,CAAA,IAAA,CAAK,MAAA,EAAQ,aAAa,CAAC,CAAA,CAAE,CAAA;AAC5D,EAAA,OAAA,CAAQ,IAAI,iEAAuD,CAAA;AACrE,CAAC,CAAA;AAEH,OAAA,CACG,QAAQ,uBAAuB,CAAA,CAC/B,YAAY,+BAA+B,CAAA,CAC3C,OAAO,kBAAA,EAAoB,kBAAA,EAAoB,2BAA2B,CAAA,CAC1E,OAAO,qBAAA,EAAuB,mCAAmC,EACjE,MAAA,CAAO,OAAO,eAAe,OAAA,KAAY;AACxC,EAAA,IAAI;AACF,IAAA,MAAM,UAAA,GAAa,MAASC,cAAA,CAAA,QAAA,CAAS,OAAA,CAAQ,KAAK,OAAO,CAAA;AACzD,IAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,gBAAA;AAAA,MACvC,aAAA;AAAA,MACA,WAAW,IAAA,EAAK;AAAA,MAChB,OAAA,CAAQ;AAAA,KACV;AACA,IAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,sCAAA,EAAsC,UAAU,CAAA,CAAE,CAAA;AAAA,EAChE,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,UAAU,KAAK,CAAA;AAC7B,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAEH,OAAA,CAAQ,KAAA,EAAM","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 nur public.key, nicht private.key\n const publicKeyPath = path.join(extensionDir, \"public.key\");\n if (fsSync.existsSync(publicKeyPath)) {\n await fs.copyFile(publicKeyPath, path.join(tempExtensionDir, \"public.key\"));\n }\n\n // Schreibe manifest.json mit leerer Signatur ins temp haextension Verzeichnis\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 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","#!/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","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\n filesForHashing.sort((a, b) => a.path.localeCompare(b.path));\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,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
- import * as fs2 from 'fs/promises';
3
+ import * as fs from 'fs/promises';
4
4
  import * as path from 'path';
5
5
  import { resolve } from 'path';
6
6
  import { webcrypto } from 'crypto';
@@ -120,7 +120,7 @@ var ExtensionSigner = class {
120
120
  }
121
121
  const contents = [];
122
122
  for (const file of sortedFiles) {
123
- const content = await fs2.readFile(file);
123
+ const content = await fs.readFile(file);
124
124
  contents.push(content);
125
125
  }
126
126
  const combined = Buffer.concat(contents);
@@ -162,7 +162,7 @@ var ExtensionSigner = class {
162
162
  static async packageExtension(extensionPath, privateKeyHex, outputPath) {
163
163
  const extensionDir = getExtensionDir();
164
164
  const manifestPath = path.join(extensionDir, "manifest.json");
165
- const originalManifestContent = await fs2.readFile(manifestPath, "utf-8");
165
+ const originalManifestContent = await fs.readFile(manifestPath, "utf-8");
166
166
  const manifestObject = readManifest({
167
167
  rootDir: process.cwd(),
168
168
  extensionDir
@@ -186,25 +186,34 @@ var ExtensionSigner = class {
186
186
  const canonicalManifestForHashing = this.sortObjectKeysRecursively(manifest);
187
187
  const { tmpdir } = await import('os');
188
188
  const tempDir = path.join(tmpdir(), `haex-signing-${Date.now()}`);
189
- await fs2.mkdir(tempDir, { recursive: true });
189
+ await fs.mkdir(tempDir, { recursive: true });
190
190
  let contentHash;
191
191
  try {
192
192
  const { execSync } = await import('child_process');
193
193
  execSync(`cp -r "${extensionPath}/"* "${tempDir}/"`, { stdio: "ignore" });
194
194
  const tempExtensionDir = path.join(tempDir, extensionDir);
195
- await fs2.mkdir(tempExtensionDir, { recursive: true });
196
- const publicKeyPath = path.join(extensionDir, "public.key");
197
- if (fsSync.existsSync(publicKeyPath)) {
198
- await fs2.copyFile(publicKeyPath, path.join(tempExtensionDir, "public.key"));
195
+ 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
+ }
199
208
  }
200
209
  const tempManifestPath = path.join(tempExtensionDir, "manifest.json");
201
- await fs2.writeFile(
210
+ await fs.writeFile(
202
211
  tempManifestPath,
203
212
  JSON.stringify(canonicalManifestForHashing, null, 2)
204
213
  );
205
214
  const configPath = path.join(process.cwd(), "haextension.config.json");
206
215
  if (fsSync.existsSync(configPath)) {
207
- await fs2.copyFile(configPath, path.join(tempDir, "haextension.config.json"));
216
+ await fs.copyFile(configPath, path.join(tempDir, "haextension.config.json"));
208
217
  }
209
218
  if (manifest.migrationsDir) {
210
219
  const config = readHaextensionConfig(process.cwd());
@@ -212,7 +221,7 @@ var ExtensionSigner = class {
212
221
  const migrationsSourcePath = path.join(process.cwd(), migrationsSourceDir);
213
222
  if (fsSync.existsSync(migrationsSourcePath)) {
214
223
  const tempMigrationsPath = path.join(tempDir, manifest.migrationsDir);
215
- await fs2.mkdir(path.dirname(tempMigrationsPath), { recursive: true });
224
+ await fs.mkdir(path.dirname(tempMigrationsPath), { recursive: true });
216
225
  const { execSync: execSync2 } = await import('child_process');
217
226
  execSync2(`cp -r "${migrationsSourcePath}" "${tempMigrationsPath}"`, { stdio: "ignore" });
218
227
  console.log(`\u2713 Migrations copied from ${migrationsSourceDir} to ${manifest.migrationsDir}`);
@@ -222,7 +231,7 @@ var ExtensionSigner = class {
222
231
  }
223
232
  contentHash = await this.hashDirectory(tempDir);
224
233
  } finally {
225
- await fs2.rm(tempDir, { recursive: true, force: true }).catch(() => {
234
+ await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {
226
235
  });
227
236
  }
228
237
  const signatureBuffer = await webcrypto.subtle.sign(
@@ -232,21 +241,29 @@ var ExtensionSigner = class {
232
241
  );
233
242
  const signatureHex = Buffer.from(signatureBuffer).toString("hex");
234
243
  manifest.signature = signatureHex;
235
- await fs2.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
244
+ await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
236
245
  const finalOutputPath = outputPath || `${manifest.name}-${manifest.version}${EXTENSION_FILE_EXTENSION}`;
237
246
  const output = fsSync.createWriteStream(finalOutputPath);
238
247
  const archive = archiver("zip", { zlib: { level: 9 } });
239
248
  return new Promise((resolve3, reject) => {
240
249
  output.on("close", async () => {
241
- await fs2.writeFile(manifestPath, originalManifestContent);
250
+ await fs.writeFile(manifestPath, originalManifestContent);
242
251
  console.log("content_hash:", contentHash);
243
252
  console.log(
244
- `\u2713 Extension packaged!!: ${finalOutputPath} (${archive.pointer()} bytes)`
253
+ `\u2713 Extension packaged: ${finalOutputPath} (${archive.pointer()} bytes)`
245
254
  );
255
+ console.log("\n\u{1F50D} Verifying signature...");
256
+ const verifyResult = await this.verifyPackage(finalOutputPath);
257
+ if (!verifyResult.valid) {
258
+ console.error(`\u274C Signature verification failed: ${verifyResult.error}`);
259
+ reject(new Error(`Signature verification failed: ${verifyResult.error}`));
260
+ return;
261
+ }
262
+ console.log("\u2713 Signature verified successfully!");
246
263
  resolve3(finalOutputPath);
247
264
  });
248
265
  output.on("error", (err) => {
249
- fs2.writeFile(manifestPath, originalManifestContent).finally(
266
+ fs.writeFile(manifestPath, originalManifestContent).finally(
250
267
  () => reject(err)
251
268
  );
252
269
  });
@@ -292,7 +309,7 @@ var ExtensionSigner = class {
292
309
  }, {});
293
310
  }
294
311
  static async getAllFiles(dirPath) {
295
- const entries = await fs2.readdir(dirPath, { withFileTypes: true });
312
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
296
313
  const files = await Promise.all(
297
314
  entries.map(async (entry) => {
298
315
  const fullPath = path.join(dirPath, entry.name);
@@ -323,6 +340,72 @@ var ExtensionSigner = class {
323
340
  );
324
341
  return new Uint8Array(await webcrypto.subtle.exportKey("raw", publicKey));
325
342
  }
343
+ /**
344
+ * Verifies the signature of a packaged extension (.xt file)
345
+ */
346
+ static async verifyPackage(packagePath) {
347
+ const JSZip = (await import('jszip')).default;
348
+ try {
349
+ const zipBuffer = await fs.readFile(packagePath);
350
+ const zip = await JSZip.loadAsync(zipBuffer);
351
+ const manifestFile = zip.file("haextension/manifest.json");
352
+ if (!manifestFile) {
353
+ return { valid: false, error: "manifest.json not found in package" };
354
+ }
355
+ const manifestContent = await manifestFile.async("string");
356
+ const manifest = JSON.parse(manifestContent);
357
+ const { publicKey: publicKeyHex, signature: signatureHex } = manifest;
358
+ if (!publicKeyHex || !signatureHex) {
359
+ return { valid: false, error: "Missing publicKey or signature in manifest" };
360
+ }
361
+ const files = [];
362
+ for (const filePath of Object.keys(zip.files)) {
363
+ const entry = zip.files[filePath];
364
+ if (entry && !entry.dir) {
365
+ const content = await entry.async("uint8array");
366
+ files.push({ path: filePath, content });
367
+ }
368
+ }
369
+ const manifestForHashing = this.sortObjectKeysRecursively({
370
+ ...manifest,
371
+ signature: ""
372
+ });
373
+ const manifestBytes = new TextEncoder().encode(JSON.stringify(manifestForHashing, null, 2));
374
+ const filesForHashing = files.map((file) => {
375
+ if (file.path === "haextension/manifest.json") {
376
+ return { path: file.path, content: manifestBytes };
377
+ }
378
+ return file;
379
+ });
380
+ filesForHashing.sort((a, b) => a.path.localeCompare(b.path));
381
+ const totalLength = filesForHashing.reduce((sum, f) => sum + f.content.length, 0);
382
+ const combined = new Uint8Array(totalLength);
383
+ let offset = 0;
384
+ for (const file of filesForHashing) {
385
+ combined.set(file.content, offset);
386
+ offset += file.content.length;
387
+ }
388
+ const hashBuffer = await webcrypto.subtle.digest("SHA-256", combined);
389
+ const publicKeyBuffer = Buffer.from(publicKeyHex, "hex");
390
+ const publicKey = await webcrypto.subtle.importKey(
391
+ "raw",
392
+ publicKeyBuffer,
393
+ { name: "Ed25519", namedCurve: "Ed25519" },
394
+ false,
395
+ ["verify"]
396
+ );
397
+ const signatureBuffer = Buffer.from(signatureHex, "hex");
398
+ const isValid = await webcrypto.subtle.verify(
399
+ "Ed25519",
400
+ publicKey,
401
+ signatureBuffer,
402
+ hashBuffer
403
+ );
404
+ return { valid: isValid, error: isValid ? void 0 : "Signature does not match" };
405
+ } catch (err) {
406
+ return { valid: false, error: err instanceof Error ? err.message : "Unknown error" };
407
+ }
408
+ }
326
409
  };
327
410
  var program = new Command();
328
411
  program.name("haexhub").description("HaexHub Extension Development Tools").version("1.0.0");
@@ -337,15 +420,15 @@ program.command("init").description("Initialize a new HaexHub extension in your
337
420
  let packageJson = {};
338
421
  const packageJsonPath = path.join(cwd, "package.json");
339
422
  if (existsSync(packageJsonPath)) {
340
- const content = await fs2.readFile(packageJsonPath, "utf-8");
423
+ const content = await fs.readFile(packageJsonPath, "utf-8");
341
424
  packageJson = JSON.parse(content);
342
425
  }
343
426
  console.log("\u{1F680} Initializing HaexHub Extension...\n");
344
- await fs2.mkdir(extDir, { recursive: true });
427
+ await fs.mkdir(extDir, { recursive: true });
345
428
  console.log(`\u2713 Created directory: ${options.dir}`);
346
429
  const { publicKey, privateKey } = await ExtensionSigner.generateKeypair();
347
- await fs2.writeFile(path.join(extDir, "public.key"), publicKey);
348
- await fs2.writeFile(path.join(extDir, "private.key"), privateKey);
430
+ await fs.writeFile(path.join(extDir, "public.key"), publicKey);
431
+ await fs.writeFile(path.join(extDir, "private.key"), privateKey);
349
432
  console.log("\u2713 Generated keypair");
350
433
  const manifest = {
351
434
  publicKey,
@@ -364,7 +447,7 @@ program.command("init").description("Initialize a new HaexHub extension in your
364
447
  } else if (!packageJson.description) {
365
448
  manifest.description = "A HaexHub extension";
366
449
  }
367
- await fs2.writeFile(
450
+ await fs.writeFile(
368
451
  path.join(extDir, "manifest.json"),
369
452
  JSON.stringify(manifest, null, 2)
370
453
  );
@@ -377,13 +460,13 @@ program.command("init").description("Initialize a new HaexHub extension in your
377
460
  `*${EXTENSION_FILE_EXTENSION}`
378
461
  ];
379
462
  if (existsSync(gitignorePath)) {
380
- const existing = await fs2.readFile(gitignorePath, "utf-8");
463
+ const existing = await fs.readFile(gitignorePath, "utf-8");
381
464
  if (!existing.includes(`${gitignoreDir}/private.key`)) {
382
- await fs2.appendFile(gitignorePath, gitignoreEntries.join("\n"));
465
+ await fs.appendFile(gitignorePath, gitignoreEntries.join("\n"));
383
466
  console.log("\u2713 Updated .gitignore");
384
467
  }
385
468
  } else {
386
- await fs2.writeFile(gitignorePath, gitignoreEntries.join("\n"));
469
+ await fs.writeFile(gitignorePath, gitignoreEntries.join("\n"));
387
470
  console.log("\u2713 Created .gitignore");
388
471
  }
389
472
  const config = {
@@ -400,7 +483,7 @@ program.command("init").description("Initialize a new HaexHub extension in your
400
483
  distDir: "dist"
401
484
  }
402
485
  };
403
- await fs2.writeFile(
486
+ await fs.writeFile(
404
487
  path.join(cwd, "haextension.config.json"),
405
488
  JSON.stringify(config, null, 2)
406
489
  );
@@ -409,7 +492,7 @@ program.command("init").description("Initialize a new HaexHub extension in your
409
492
  packageJson.scripts = packageJson.scripts || {};
410
493
  packageJson.scripts["ext:dev"] = packageJson.scripts["ext:dev"] || "haexhub dev";
411
494
  packageJson.scripts["ext:build"] = packageJson.scripts["ext:build"] || `${packageJson.scripts.build || "vite build"} && haexhub sign dist -k ${options.dir}/private.key`;
412
- await fs2.writeFile(
495
+ await fs.writeFile(
413
496
  packageJsonPath,
414
497
  JSON.stringify(packageJson, null, 2)
415
498
  );
@@ -431,9 +514,9 @@ program.command("init").description("Initialize a new HaexHub extension in your
431
514
  program.command("keygen").description("Generate a new keypair for signing extensions").option("-o, --output <path>", "Output directory", "./haextension").action(async (options) => {
432
515
  const { publicKey, privateKey } = await ExtensionSigner.generateKeypair();
433
516
  const keyDir = path.resolve(options.output);
434
- await fs2.mkdir(keyDir, { recursive: true });
435
- await fs2.writeFile(path.join(keyDir, "public.key"), publicKey);
436
- await fs2.writeFile(path.join(keyDir, "private.key"), privateKey);
517
+ await fs.mkdir(keyDir, { recursive: true });
518
+ await fs.writeFile(path.join(keyDir, "public.key"), publicKey);
519
+ await fs.writeFile(path.join(keyDir, "private.key"), privateKey);
437
520
  console.log("\u2713 Keypair generated:");
438
521
  console.log(` Public: ${path.join(keyDir, "public.key")}`);
439
522
  console.log(` Private: ${path.join(keyDir, "private.key")}`);
@@ -441,7 +524,7 @@ program.command("keygen").description("Generate a new keypair for signing extens
441
524
  });
442
525
  program.command("sign <extension-path>").description("Sign and package an extension").option("-k, --key <path>", "Private key file", "./haextension/private.key").option("-o, --output <path>", "Output path for .haextension file").action(async (extensionPath, options) => {
443
526
  try {
444
- const privateKey = await fs2.readFile(options.key, "utf-8");
527
+ const privateKey = await fs.readFile(options.key, "utf-8");
445
528
  const outputPath = await ExtensionSigner.packageExtension(
446
529
  extensionPath,
447
530
  privateKey.trim(),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/config.ts","../../src/manifest.ts","../../src/crypto/signing.ts","../../src/cli/index.ts"],"names":["resolvePath","readFileSync","fs","execSync","resolve","path2","existsSync"],"mappings":"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","file":"index.mjs","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 nur public.key, nicht private.key\n const publicKeyPath = path.join(extensionDir, \"public.key\");\n if (fsSync.existsSync(publicKeyPath)) {\n await fs.copyFile(publicKeyPath, path.join(tempExtensionDir, \"public.key\"));\n }\n\n // Schreibe manifest.json mit leerer Signatur ins temp haextension Verzeichnis\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 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","#!/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":["resolvePath","readFileSync","stat","execSync","resolve","path2","existsSync","fs2"],"mappings":"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","file":"index.mjs","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\n filesForHashing.sort((a, b) => a.path.localeCompare(b.path));\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haex-space/vault-sdk",
3
- "version": "2.3.4",
3
+ "version": "2.3.6",
4
4
  "description": "SDK for building Haex Vault extensions",
5
5
  "repository": {
6
6
  "type": "git",
@@ -106,7 +106,8 @@
106
106
  "dependencies": {
107
107
  "archiver": "^7.0.1",
108
108
  "commander": "^14.0.1",
109
- "drizzle-orm": "^0.45.0"
109
+ "drizzle-orm": "^0.45.0",
110
+ "jszip": "^3.10.1"
110
111
  },
111
112
  "scripts": {
112
113
  "build": "tsup src/index.ts src/node.ts src/cli/index.ts src/vue.ts src/react.ts src/svelte.ts src/nuxt.ts src/vite.ts src/runtime/nuxt.plugin.client.ts --format cjs,esm --dts --external @nuxt/kit --external nuxt --external vite --external vue --external react --external svelte --external svelte/store && cp src/runtime/nuxt.types.d.ts dist/runtime/nuxt.types.d.ts",