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