@haex-space/vault-sdk 2.2.0 → 2.2.2

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
@@ -56,35 +56,43 @@ function readManifest(options) {
56
56
  try {
57
57
  const manifestContent = fsSync.readFileSync(resolvedManifestPath, "utf-8");
58
58
  const parsed = JSON.parse(manifestContent);
59
- let version = parsed.version;
59
+ let packageJson = {};
60
+ try {
61
+ const packageJsonPath = path2.resolve(rootDir, "package.json");
62
+ packageJson = JSON.parse(fsSync.readFileSync(packageJsonPath, "utf-8"));
63
+ } catch (pkgError) {
64
+ console.warn(`[@haexhub/sdk] Warning: Could not read package.json`);
65
+ }
66
+ const name = parsed.name ?? packageJson.name;
67
+ const version = parsed.version ?? packageJson.version;
68
+ const author = parsed.author ?? packageJson.author ?? null;
69
+ const homepage = parsed.homepage ?? packageJson.homepage ?? null;
70
+ if (!name) {
71
+ console.warn(`[@haexhub/sdk] Warning: No name found in manifest or package.json`);
72
+ return null;
73
+ }
60
74
  if (!version) {
61
- try {
62
- const packageJsonPath = path2.resolve(rootDir, "package.json");
63
- const packageJson = JSON.parse(fsSync.readFileSync(packageJsonPath, "utf-8"));
64
- version = packageJson.version;
65
- console.log(`\u2713 [@haexhub/sdk] Using version from package.json: ${version}`);
66
- } catch (pkgError) {
67
- console.warn(`[@haexhub/sdk] Warning: Could not read version from package.json`);
68
- }
75
+ console.warn(`[@haexhub/sdk] Warning: No version found in manifest or package.json`);
76
+ return null;
69
77
  }
70
78
  const manifest = {
71
- name: parsed.name,
79
+ name,
72
80
  version,
73
- author: parsed.author ?? null,
81
+ author,
74
82
  entry: parsed.entry ?? null,
75
83
  icon: parsed.icon ?? null,
76
- public_key: parsed.public_key,
77
- signature: parsed.signature || "",
78
- permissions: parsed.permissions || {
84
+ publicKey: parsed.publicKey ?? "",
85
+ signature: parsed.signature ?? "",
86
+ permissions: parsed.permissions ?? {
79
87
  database: [],
80
88
  filesystem: [],
81
89
  http: [],
82
90
  shell: []
83
91
  },
84
- homepage: parsed.homepage ?? null,
92
+ homepage,
85
93
  description: parsed.description ?? null,
86
- single_instance: parsed.single_instance ?? null,
87
- display_mode: parsed.display_mode ?? null
94
+ singleInstance: parsed.singleInstance ?? null,
95
+ displayMode: parsed.displayMode ?? null
88
96
  };
89
97
  console.log(`\u2713 [@haexhub/sdk] Loaded ${resolvedManifestPath}`);
90
98
  return manifest;
@@ -186,7 +194,7 @@ var ExtensionSigner = class {
186
194
  if (!manifestObject) {
187
195
  throw new Error("Failed to read manifest.json");
188
196
  }
189
- const manifest = manifestObject;
197
+ const manifest = { ...manifestObject };
190
198
  const privateKeyBuffer = Buffer.from(privateKeyHex, "hex");
191
199
  const privateKey = await crypto.webcrypto.subtle.importKey(
192
200
  "pkcs8",
@@ -197,7 +205,7 @@ var ExtensionSigner = class {
197
205
  );
198
206
  const publicKeyBuffer = await this.derivePublicKey(privateKeyBuffer);
199
207
  const publicKeyHex = Buffer.from(publicKeyBuffer).toString("hex");
200
- manifest.public_key = publicKeyHex;
208
+ manifest.publicKey = publicKeyHex;
201
209
  manifest.signature = "";
202
210
  const canonicalManifestForHashing = this.sortObjectKeysRecursively(manifest);
203
211
  const { tmpdir } = await import('os');
@@ -333,7 +341,6 @@ program.command("init").description("Initialize a new HaexHub extension in your
333
341
  const content = await fs2__namespace.readFile(packageJsonPath, "utf-8");
334
342
  packageJson = JSON.parse(content);
335
343
  }
336
- const extensionName = options.name || packageJson.name || path2__namespace.basename(cwd).replace(/[^a-z0-9-]/gi, "-").toLowerCase();
337
344
  console.log("\u{1F680} Initializing HaexHub Extension...\n");
338
345
  await fs2__namespace.mkdir(extDir, { recursive: true });
339
346
  console.log(`\u2713 Created directory: ${options.dir}`);
@@ -342,13 +349,7 @@ program.command("init").description("Initialize a new HaexHub extension in your
342
349
  await fs2__namespace.writeFile(path2__namespace.join(extDir, "private.key"), privateKey);
343
350
  console.log("\u2713 Generated keypair");
344
351
  const manifest = {
345
- name: extensionName,
346
- version: packageJson.version || "0.1.0",
347
- author: options.author || packageJson.author || "Your Name",
348
- description: options.description || packageJson.description || "A HaexHub extension",
349
- entry: "index.html",
350
- icon: "icon.png",
351
- public_key: publicKey,
352
+ publicKey,
352
353
  signature: "",
353
354
  permissions: {
354
355
  database: [],
@@ -356,10 +357,14 @@ program.command("init").description("Initialize a new HaexHub extension in your
356
357
  http: [],
357
358
  shell: []
358
359
  },
359
- homepage: packageJson.homepage || null,
360
- single_instance: false,
361
- display_mode: "auto"
360
+ singleInstance: false,
361
+ displayMode: "auto"
362
362
  };
363
+ if (options.description) {
364
+ manifest.description = options.description;
365
+ } else if (!packageJson.description) {
366
+ manifest.description = "A HaexHub extension";
367
+ }
363
368
  await fs2__namespace.writeFile(
364
369
  path2__namespace.join(extDir, "manifest.json"),
365
370
  JSON.stringify(manifest, null, 2)
@@ -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","archiver","Command","path2","fs2"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBO,SAAS,qBAAA,CAAsB,OAAA,GAAkB,OAAA,CAAQ,GAAA,EAAI,EAA6B;AAC/F,EAAA,MAAM,UAAA,GAAaA,aAAA,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;AC3BO,SAAS,aAAa,OAAA,EAAwD;AACnF,EAAA,MAAM,EAAE,OAAA,EAAS,YAAA,EAAc,YAAA,GAAe,eAAc,GAAI,OAAA;AAGhE,EAAA,MAAM,oBAAA,GAAuB,eACzBC,aAAA,CAAY,OAAA,EAAS,YAAY,CAAA,GACjCA,aAAA,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,GAAS,IAAA,CAAK,KAAA,CAAM,eAAe,CAAA;AAGzC,IAAA,IAAI,UAAU,MAAA,CAAO,OAAA;AACrB,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,IAAI;AACF,QAAA,MAAM,eAAA,GAAkBC,aAAA,CAAY,OAAA,EAAS,cAAc,CAAA;AAC3D,QAAA,MAAM,cAAc,IAAA,CAAK,KAAA,CAAMD,mBAAAA,CAAa,eAAA,EAAiB,OAAO,CAAC,CAAA;AACrE,QAAA,OAAA,GAAU,WAAA,CAAY,OAAA;AACtB,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,uDAAA,EAAqD,OAAO,CAAA,CAAE,CAAA;AAAA,MAC5E,SAAS,QAAA,EAAU;AACjB,QAAA,OAAA,CAAQ,KAAK,CAAA,gEAAA,CAAkE,CAAA;AAAA,MACjF;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAA8B;AAAA,MAClC,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,OAAA;AAAA,MACA,MAAA,EAAQ,OAAO,MAAA,IAAU,IAAA;AAAA,MACzB,KAAA,EAAO,OAAO,KAAA,IAAS,IAAA;AAAA,MACvB,IAAA,EAAM,OAAO,IAAA,IAAQ,IAAA;AAAA,MACrB,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,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,EAAU,OAAO,QAAA,IAAY,IAAA;AAAA,MAC7B,WAAA,EAAa,OAAO,WAAA,IAAe,IAAA;AAAA,MACnC,eAAA,EAAiB,OAAO,eAAA,IAAmB,IAAA;AAAA,MAC3C,YAAA,EAAc,OAAO,YAAA,IAAgB;AAAA,KACvC;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,6BAAA,EAA2B,oBAAoB,CAAA,CAAE,CAAA;AAC7D,IAAA,OAAO,QAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,sDAAsD,oBAAoB,CAAA,sCAAA;AAAA,KAC5E;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;AChEO,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,gBAAA,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,gBAAA,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,cAAA;AAGjB,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,UAAA,GAAa,YAAA;AACtB,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,sBAAK,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,gBAAA,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,gBAAA,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,gBAAA,CAAA,IAAA,CAAK,gBAAA,EAAkB,YAAY,CAAC,CAAA;AAAA,MAC5E;AAGA,MAAA,MAAM,gBAAA,GAAwBA,gBAAA,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,gBAAA,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,gBAAA,CAAA,IAAA,CAAK,OAAA,EAAS,yBAAyB,CAAC,CAAA;AAAA,MAC7E;AAGA,MAAA,WAAA,GAAc,MAAM,IAAA,CAAK,aAAA,CAAc,OAAO,CAAA;AAAA,IAChD,CAAA,SAAE;AAEA,MAAA,MAASC,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,GAAUC,0BAAS,KAAA,EAAO,EAAE,MAAM,EAAE,KAAA,EAAO,CAAA,EAAE,EAAG,CAAA;AAEtD,IAAA,OAAO,IAAI,OAAA,CAAQ,CAACR,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,gBAAA,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;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,gBAAA,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;ACjTA,IAAM,OAAA,GAAU,IAAIK,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,gBAAA,CAAA,OAAA,CAAQ,GAAA,EAAK,OAAA,CAAQ,GAAG,CAAA;AAG5C,IAAA,IAAIT,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,GAAuBS,gBAAA,CAAA,IAAA,CAAK,GAAA,EAAK,cAAc,CAAA;AACrD,IAAA,IAAIT,iBAAAA,CAAW,eAAe,CAAA,EAAG;AAC/B,MAAA,MAAM,OAAA,GAAU,MAASU,cAAA,CAAA,QAAA,CAAS,eAAA,EAAiB,OAAO,CAAA;AAC1D,MAAA,WAAA,GAAc,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IAClC;AAGA,IAAA,MAAM,aAAA,GACJ,OAAA,CAAQ,IAAA,IACR,WAAA,CAAY,IAAA,IACPD,gBAAA,CAAA,QAAA,CAAS,GAAG,CAAA,CAAE,OAAA,CAAQ,cAAA,EAAgB,GAAG,CAAA,CAAE,WAAA,EAAY;AAE9D,IAAA,OAAA,CAAQ,IAAI,+CAAwC,CAAA;AAGpD,IAAA,MAASC,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,gBAAA,CAAA,IAAA,CAAK,MAAA,EAAQ,YAAY,GAAG,SAAS,CAAA;AAC7D,IAAA,MAASC,cAAA,CAAA,SAAA,CAAeD,gBAAA,CAAA,IAAA,CAAK,MAAA,EAAQ,aAAa,GAAG,UAAU,CAAA;AAC/D,IAAA,OAAA,CAAQ,IAAI,0BAAqB,CAAA;AAGjC,IAAA,MAAM,QAAA,GAAW;AAAA,MACf,IAAA,EAAM,aAAA;AAAA,MACN,OAAA,EAAS,YAAY,OAAA,IAAW,OAAA;AAAA,MAChC,MAAA,EAAQ,OAAA,CAAQ,MAAA,IAAU,WAAA,CAAY,MAAA,IAAU,WAAA;AAAA,MAChD,WAAA,EACE,OAAA,CAAQ,WAAA,IACR,WAAA,CAAY,WAAA,IACZ,qBAAA;AAAA,MACF,KAAA,EAAO,YAAA;AAAA,MACP,IAAA,EAAM,UAAA;AAAA,MACN,UAAA,EAAY,SAAA;AAAA,MACZ,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,QAAA,EAAU,YAAY,QAAA,IAAY,IAAA;AAAA,MAClC,eAAA,EAAiB,KAAA;AAAA,MACjB,YAAA,EAAc;AAAA,KAChB;AAEA,IAAA,MAASC,cAAA,CAAA,SAAA;AAAA,MACFD,gBAAA,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,gBAAA,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,IAAIT,iBAAAA,CAAW,aAAa,CAAA,EAAG;AAC7B,MAAA,MAAM,QAAA,GAAW,MAASU,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,gBAAA,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,IAAIT,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,MAASU,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,gBAAA,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,gBAAA,CAAA,IAAA,CAAK,MAAA,EAAQ,YAAY,GAAG,SAAS,CAAA;AAC7D,EAAA,MAASC,cAAA,CAAA,SAAA,CAAeD,gBAAA,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,gBAAA,CAAA,IAAA,CAAK,MAAA,EAAQ,YAAY,CAAC,CAAA,CAAE,CAAA;AAC3D,EAAA,OAAA,CAAQ,IAAI,CAAA,WAAA,EAAmBA,gBAAA,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}\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 = JSON.parse(manifestContent);\n\n // Read version from package.json if not provided in manifest\n let version = parsed.version;\n if (!version) {\n try {\n const packageJsonPath = resolvePath(rootDir, \"package.json\");\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n version = packageJson.version;\n console.log(`✓ [@haexhub/sdk] Using version from package.json: ${version}`);\n } catch (pkgError) {\n console.warn(`[@haexhub/sdk] Warning: Could not read version from package.json`);\n }\n }\n\n const manifest: ExtensionManifest = {\n name: parsed.name,\n version: version,\n author: parsed.author ?? null,\n entry: parsed.entry ?? null,\n icon: parsed.icon ?? null,\n public_key: parsed.public_key,\n signature: parsed.signature || \"\",\n permissions: parsed.permissions || {\n database: [],\n filesystem: [],\n http: [],\n shell: [],\n },\n homepage: parsed.homepage ?? null,\n description: parsed.description ?? null,\n single_instance: parsed.single_instance ?? null,\n display_mode: parsed.display_mode ?? null,\n };\n\n console.log(`✓ [@haexhub/sdk] Loaded ${resolvedManifestPath}`);\n return manifest;\n } catch (error) {\n console.warn(\n `[@haexhub/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 } 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 as any; // Cast to any for manipulation\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.public_key = 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 // 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 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 // Determine extension name\n const extensionName =\n options.name ||\n packageJson.name ||\n path.basename(cwd).replace(/[^a-z0-9-]/gi, \"-\").toLowerCase();\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\n const manifest = {\n name: extensionName,\n version: packageJson.version || \"0.1.0\",\n author: options.author || packageJson.author || \"Your Name\",\n description:\n options.description ||\n packageJson.description ||\n \"A HaexHub extension\",\n entry: \"index.html\",\n icon: \"icon.png\",\n public_key: publicKey,\n signature: \"\",\n permissions: {\n database: [],\n filesystem: [],\n http: [],\n shell: [],\n },\n homepage: packageJson.homepage || null,\n single_instance: false,\n display_mode: \"auto\",\n };\n\n await fs.writeFile(\n path.join(extDir, \"manifest.json\"),\n JSON.stringify(manifest, null, 2)\n );\n console.log(\"✓ Created manifest.json\");\n\n // 4. Create/update .gitignore\n const gitignorePath = path.join(cwd, \".gitignore\");\n // Remove leading ./ from dir path for gitignore\n const gitignoreDir = options.dir.replace(/^\\.\\//, '');\n const gitignoreEntries = [\n \"\\n# HaexHub Extension\",\n `${gitignoreDir}/private.key`,\n `*${EXTENSION_FILE_EXTENSION}`,\n ];\n\n if (existsSync(gitignorePath)) {\n const existing = await fs.readFile(gitignorePath, \"utf-8\");\n if (!existing.includes(`${gitignoreDir}/private.key`)) {\n await fs.appendFile(gitignorePath, gitignoreEntries.join(\"\\n\"));\n console.log(\"✓ Updated .gitignore\");\n }\n } else {\n await fs.writeFile(gitignorePath, gitignoreEntries.join(\"\\n\"));\n console.log(\"✓ Created .gitignore\");\n }\n\n // 5. Create haextension.config.json\n const config = {\n dev: {\n port: 5173,\n host: \"localhost\",\n haextension_dir: options.dir,\n },\n keys: {\n public_key_path: `${options.dir}/public.key`,\n private_key_path: `${options.dir}/private.key`,\n },\n build: {\n distDir: \"dist\",\n },\n };\n\n await fs.writeFile(\n path.join(cwd, \"haextension.config.json\"),\n JSON.stringify(config, null, 2)\n );\n console.log(\"✓ Created haextension.config.json\");\n\n // 6. Update package.json scripts\n if (existsSync(packageJsonPath)) {\n packageJson.scripts = packageJson.scripts || {};\n packageJson.scripts[\"ext:dev\"] =\n packageJson.scripts[\"ext:dev\"] || \"haexhub dev\";\n packageJson.scripts[\"ext:build\"] =\n packageJson.scripts[\"ext:build\"] ||\n `${packageJson.scripts.build || \"vite build\"} && haexhub sign dist -k ${options.dir}/private.key`;\n\n await fs.writeFile(\n packageJsonPath,\n JSON.stringify(packageJson, null, 2)\n );\n console.log(\"✓ Updated package.json scripts\");\n }\n\n console.log(\"\\n✨ Extension initialized successfully!\\n\");\n console.log(\"📝 Next steps:\");\n console.log(` 1. Edit ${options.dir}/manifest.json to configure your extension`);\n console.log(\" 2. Run 'npm run ext:dev' to start development mode\");\n console.log(\" 3. Run 'npm run ext:build' to build and sign your extension\");\n console.log(\"\\n⚠️ Important: Never commit your private key:\");\n console.log(` - ${options.dir}/private.key has been added to .gitignore`);\n console.log(\" - haextension.config.json is safe to commit (contains only paths)\\n\");\n } catch (error) {\n console.error(\"❌ Error:\", error);\n process.exit(1);\n }\n });\n\nprogram\n .command(\"keygen\")\n .description(\"Generate a new keypair for signing extensions\")\n .option(\"-o, --output <path>\", \"Output directory\", \"./haextension\")\n .action(async (options) => {\n const { publicKey, privateKey } = await ExtensionSigner.generateKeypair();\n\n const keyDir = path.resolve(options.output);\n await fs.mkdir(keyDir, { recursive: true });\n\n await fs.writeFile(path.join(keyDir, \"public.key\"), publicKey);\n await fs.writeFile(path.join(keyDir, \"private.key\"), privateKey);\n\n console.log(\"✓ Keypair generated:\");\n console.log(` Public: ${path.join(keyDir, \"public.key\")}`);\n console.log(` Private: ${path.join(keyDir, \"private.key\")}`);\n console.log(\"\\n⚠️ Keep your private key safe and never commit it!\");\n });\n\nprogram\n .command(\"sign <extension-path>\")\n .description(\"Sign and package an extension\")\n .option(\"-k, --key <path>\", \"Private key file\", \"./haextension/private.key\")\n .option(\"-o, --output <path>\", \"Output path for .haextension file\")\n .action(async (extensionPath, options) => {\n try {\n const privateKey = await fs.readFile(options.key, \"utf-8\");\n const outputPath = await ExtensionSigner.packageExtension(\n extensionPath,\n privateKey.trim(),\n options.output\n );\n console.log(`\\n✓ Extension signed and packaged: ${outputPath}`);\n } catch (error) {\n console.error(\"Error:\", error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n"]}
1
+ {"version":3,"sources":["../../src/config.ts","../../src/manifest.ts","../../src/crypto/signing.ts","../../src/cli/index.ts"],"names":["resolve","existsSync","readFileSync","resolvePath","webcrypto","path","fs","fsSync","archiver","Command","path2","fs2"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Utility to read haextension.config.json\n */\nimport { readFileSync, existsSync } from 'fs'\nimport { resolve } from 'path'\n\nexport interface HaextensionConfig {\n dev?: {\n port?: number\n host?: string\n haextension_dir?: string\n }\n keys?: {\n public_key_path?: string\n private_key_path?: string\n }\n build?: {\n distDir?: string\n }\n}\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(`[@haexhub/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(`[@haexhub/sdk] Warning: No name found in manifest or package.json`);\n return null;\n }\n\n if (!version) {\n console.warn(`[@haexhub/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 };\n\n console.log(`✓ [@haexhub/sdk] Loaded ${resolvedManifestPath}`);\n return manifest;\n } catch (error) {\n console.warn(\n `[@haexhub/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 } 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 // 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 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"]}
@@ -31,35 +31,43 @@ function readManifest(options) {
31
31
  try {
32
32
  const manifestContent = readFileSync(resolvedManifestPath, "utf-8");
33
33
  const parsed = JSON.parse(manifestContent);
34
- let version = parsed.version;
34
+ let packageJson = {};
35
+ try {
36
+ const packageJsonPath = resolve(rootDir, "package.json");
37
+ packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
38
+ } catch (pkgError) {
39
+ console.warn(`[@haexhub/sdk] Warning: Could not read package.json`);
40
+ }
41
+ const name = parsed.name ?? packageJson.name;
42
+ const version = parsed.version ?? packageJson.version;
43
+ const author = parsed.author ?? packageJson.author ?? null;
44
+ const homepage = parsed.homepage ?? packageJson.homepage ?? null;
45
+ if (!name) {
46
+ console.warn(`[@haexhub/sdk] Warning: No name found in manifest or package.json`);
47
+ return null;
48
+ }
35
49
  if (!version) {
36
- try {
37
- const packageJsonPath = resolve(rootDir, "package.json");
38
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
39
- version = packageJson.version;
40
- console.log(`\u2713 [@haexhub/sdk] Using version from package.json: ${version}`);
41
- } catch (pkgError) {
42
- console.warn(`[@haexhub/sdk] Warning: Could not read version from package.json`);
43
- }
50
+ console.warn(`[@haexhub/sdk] Warning: No version found in manifest or package.json`);
51
+ return null;
44
52
  }
45
53
  const manifest = {
46
- name: parsed.name,
54
+ name,
47
55
  version,
48
- author: parsed.author ?? null,
56
+ author,
49
57
  entry: parsed.entry ?? null,
50
58
  icon: parsed.icon ?? null,
51
- public_key: parsed.public_key,
52
- signature: parsed.signature || "",
53
- permissions: parsed.permissions || {
59
+ publicKey: parsed.publicKey ?? "",
60
+ signature: parsed.signature ?? "",
61
+ permissions: parsed.permissions ?? {
54
62
  database: [],
55
63
  filesystem: [],
56
64
  http: [],
57
65
  shell: []
58
66
  },
59
- homepage: parsed.homepage ?? null,
67
+ homepage,
60
68
  description: parsed.description ?? null,
61
- single_instance: parsed.single_instance ?? null,
62
- display_mode: parsed.display_mode ?? null
69
+ singleInstance: parsed.singleInstance ?? null,
70
+ displayMode: parsed.displayMode ?? null
63
71
  };
64
72
  console.log(`\u2713 [@haexhub/sdk] Loaded ${resolvedManifestPath}`);
65
73
  return manifest;
@@ -161,7 +169,7 @@ var ExtensionSigner = class {
161
169
  if (!manifestObject) {
162
170
  throw new Error("Failed to read manifest.json");
163
171
  }
164
- const manifest = manifestObject;
172
+ const manifest = { ...manifestObject };
165
173
  const privateKeyBuffer = Buffer.from(privateKeyHex, "hex");
166
174
  const privateKey = await webcrypto.subtle.importKey(
167
175
  "pkcs8",
@@ -172,7 +180,7 @@ var ExtensionSigner = class {
172
180
  );
173
181
  const publicKeyBuffer = await this.derivePublicKey(privateKeyBuffer);
174
182
  const publicKeyHex = Buffer.from(publicKeyBuffer).toString("hex");
175
- manifest.public_key = publicKeyHex;
183
+ manifest.publicKey = publicKeyHex;
176
184
  manifest.signature = "";
177
185
  const canonicalManifestForHashing = this.sortObjectKeysRecursively(manifest);
178
186
  const { tmpdir } = await import('os');
@@ -308,7 +316,6 @@ program.command("init").description("Initialize a new HaexHub extension in your
308
316
  const content = await fs2.readFile(packageJsonPath, "utf-8");
309
317
  packageJson = JSON.parse(content);
310
318
  }
311
- const extensionName = options.name || packageJson.name || path2.basename(cwd).replace(/[^a-z0-9-]/gi, "-").toLowerCase();
312
319
  console.log("\u{1F680} Initializing HaexHub Extension...\n");
313
320
  await fs2.mkdir(extDir, { recursive: true });
314
321
  console.log(`\u2713 Created directory: ${options.dir}`);
@@ -317,13 +324,7 @@ program.command("init").description("Initialize a new HaexHub extension in your
317
324
  await fs2.writeFile(path2.join(extDir, "private.key"), privateKey);
318
325
  console.log("\u2713 Generated keypair");
319
326
  const manifest = {
320
- name: extensionName,
321
- version: packageJson.version || "0.1.0",
322
- author: options.author || packageJson.author || "Your Name",
323
- description: options.description || packageJson.description || "A HaexHub extension",
324
- entry: "index.html",
325
- icon: "icon.png",
326
- public_key: publicKey,
327
+ publicKey,
327
328
  signature: "",
328
329
  permissions: {
329
330
  database: [],
@@ -331,10 +332,14 @@ program.command("init").description("Initialize a new HaexHub extension in your
331
332
  http: [],
332
333
  shell: []
333
334
  },
334
- homepage: packageJson.homepage || null,
335
- single_instance: false,
336
- display_mode: "auto"
335
+ singleInstance: false,
336
+ displayMode: "auto"
337
337
  };
338
+ if (options.description) {
339
+ manifest.description = options.description;
340
+ } else if (!packageJson.description) {
341
+ manifest.description = "A HaexHub extension";
342
+ }
338
343
  await fs2.writeFile(
339
344
  path2.join(extDir, "manifest.json"),
340
345
  JSON.stringify(manifest, null, 2)
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/config.ts","../../src/manifest.ts","../../src/crypto/signing.ts","../../src/cli/index.ts"],"names":["resolvePath","readFileSync","path","fs","resolve","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}\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 = JSON.parse(manifestContent);\n\n // Read version from package.json if not provided in manifest\n let version = parsed.version;\n if (!version) {\n try {\n const packageJsonPath = resolvePath(rootDir, \"package.json\");\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n version = packageJson.version;\n console.log(`✓ [@haexhub/sdk] Using version from package.json: ${version}`);\n } catch (pkgError) {\n console.warn(`[@haexhub/sdk] Warning: Could not read version from package.json`);\n }\n }\n\n const manifest: ExtensionManifest = {\n name: parsed.name,\n version: version,\n author: parsed.author ?? null,\n entry: parsed.entry ?? null,\n icon: parsed.icon ?? null,\n public_key: parsed.public_key,\n signature: parsed.signature || \"\",\n permissions: parsed.permissions || {\n database: [],\n filesystem: [],\n http: [],\n shell: [],\n },\n homepage: parsed.homepage ?? null,\n description: parsed.description ?? null,\n single_instance: parsed.single_instance ?? null,\n display_mode: parsed.display_mode ?? null,\n };\n\n console.log(`✓ [@haexhub/sdk] Loaded ${resolvedManifestPath}`);\n return manifest;\n } catch (error) {\n console.warn(\n `[@haexhub/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 } 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 as any; // Cast to any for manipulation\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.public_key = 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 // 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 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 // Determine extension name\n const extensionName =\n options.name ||\n packageJson.name ||\n path.basename(cwd).replace(/[^a-z0-9-]/gi, \"-\").toLowerCase();\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\n const manifest = {\n name: extensionName,\n version: packageJson.version || \"0.1.0\",\n author: options.author || packageJson.author || \"Your Name\",\n description:\n options.description ||\n packageJson.description ||\n \"A HaexHub extension\",\n entry: \"index.html\",\n icon: \"icon.png\",\n public_key: publicKey,\n signature: \"\",\n permissions: {\n database: [],\n filesystem: [],\n http: [],\n shell: [],\n },\n homepage: packageJson.homepage || null,\n single_instance: false,\n display_mode: \"auto\",\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","path","fs","resolve","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}\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(`[@haexhub/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(`[@haexhub/sdk] Warning: No name found in manifest or package.json`);\n return null;\n }\n\n if (!version) {\n console.warn(`[@haexhub/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 };\n\n console.log(`✓ [@haexhub/sdk] Loaded ${resolvedManifestPath}`);\n return manifest;\n } catch (error) {\n console.warn(\n `[@haexhub/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 } 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 // 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 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"]}