@aixyz/cli 0.5.2 → 0.7.0

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.
@@ -37,7 +37,7 @@ export function AixyzConfigPlugin(): BunPlugin {
37
37
  return {
38
38
  name: "aixyz-config",
39
39
  setup(build) {
40
- build.onLoad({ filter: /packages\/aixyz\/config\.ts$/ }, () => ({
40
+ build.onLoad({ filter: /aixyz\/config\.ts$/ }, () => ({
41
41
  contents: `
42
42
  const config = ${JSON.stringify(materialized)};
43
43
  export function getAixyzConfig() {
package/build/icons.ts ADDED
@@ -0,0 +1,64 @@
1
+ import sharp from "sharp";
2
+ import { cpSync, existsSync, mkdirSync, writeFileSync } from "fs";
3
+ import { dirname, resolve } from "path";
4
+
5
+ /** Icon source file extensions to look for, in priority order */
6
+ const ICON_EXTENSIONS = ["svg", "png", "jpeg", "jpg"] as const;
7
+
8
+ /** Returns the first matching icon file path, or null if none found. */
9
+ export function findIconFile(appDir: string): string | null {
10
+ for (const ext of ICON_EXTENSIONS) {
11
+ const iconPath = resolve(appDir, `icon.${ext}`);
12
+ if (existsSync(iconPath)) return iconPath;
13
+ }
14
+ return null;
15
+ }
16
+
17
+ /**
18
+ * Copy the icon to destPath as icon.png.
19
+ * PNG sources are copied directly; other formats are converted via sharp.
20
+ */
21
+ export async function copyAgentIcon(iconPath: string, destPath: string): Promise<void> {
22
+ if (iconPath.endsWith(".png")) {
23
+ cpSync(iconPath, destPath);
24
+ } else {
25
+ await sharp(iconPath).png().toFile(destPath);
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Generate a favicon.ico at destPath from the given icon source.
31
+ * Uses sharp to produce a 32×32 PNG buffer, then wraps it in an ICO container.
32
+ * Modern browsers support ICO files with embedded PNG data.
33
+ */
34
+ export async function generateFavicon(iconPath: string, destPath: string): Promise<void> {
35
+ const pngData = await sharp(iconPath)
36
+ .resize(32, 32, { fit: "contain", background: { r: 0, g: 0, b: 0, alpha: 0 } })
37
+ .png()
38
+ .toBuffer();
39
+
40
+ mkdirSync(dirname(destPath), { recursive: true });
41
+ writeFileSync(destPath, buildIco(pngData, 32, 32));
42
+ }
43
+
44
+ /** Build a single-image ICO buffer with embedded PNG data. */
45
+ function buildIco(pngData: Buffer, width: number, height: number): Buffer {
46
+ // ICONDIR header (6 bytes)
47
+ const header = Buffer.alloc(6);
48
+ header.writeUInt16LE(0, 0); // reserved
49
+ header.writeUInt16LE(1, 2); // type: 1 = ICO
50
+ header.writeUInt16LE(1, 4); // image count
51
+
52
+ // ICONDIRENTRY (16 bytes); image data starts at offset 6 + 16 = 22
53
+ const entry = Buffer.alloc(16);
54
+ entry.writeUInt8(width === 256 ? 0 : width, 0); // width (0 means 256)
55
+ entry.writeUInt8(height === 256 ? 0 : height, 1); // height (0 means 256)
56
+ entry.writeUInt8(0, 2); // color count (0 = true color)
57
+ entry.writeUInt8(0, 3); // reserved
58
+ entry.writeUInt16LE(1, 4); // planes
59
+ entry.writeUInt16LE(32, 6); // bits per pixel
60
+ entry.writeUInt32LE(pngData.length, 8); // size of image data
61
+ entry.writeUInt32LE(22, 12); // offset to image data
62
+
63
+ return Buffer.concat([header, entry, pngData]);
64
+ }
package/build/index.ts CHANGED
@@ -2,6 +2,7 @@ import { resolve } from "path";
2
2
  import { existsSync, mkdirSync, cpSync, rmSync } from "fs";
3
3
  import { AixyzConfigPlugin } from "./AixyzConfigPlugin";
4
4
  import { AixyzServerPlugin, getEntrypointMayGenerate } from "./AixyzServerPlugin";
5
+ import { findIconFile, copyAgentIcon, generateFavicon } from "./icons";
5
6
  import { getAixyzConfig } from "@aixyz/config";
6
7
  import { loadEnvConfig } from "@next/env";
7
8
  import chalk from "chalk";
@@ -65,9 +66,10 @@ async function buildBun(entrypoint: string): Promise<void> {
65
66
  console.log("Copied public/ →", destPublicDir);
66
67
  }
67
68
 
68
- const iconFile = resolve(cwd, "app/icon.png");
69
- if (existsSync(iconFile)) {
70
- cpSync(iconFile, resolve(outputDir, "icon.png"));
69
+ const iconFile = findIconFile(resolve(cwd, "app"));
70
+ if (iconFile) {
71
+ await copyAgentIcon(iconFile, resolve(outputDir, "icon.png"));
72
+ await generateFavicon(iconFile, resolve(outputDir, "public/favicon.ico"));
71
73
  }
72
74
 
73
75
  // Log summary
@@ -151,11 +153,12 @@ async function buildVercel(entrypoint: string): Promise<void> {
151
153
  console.log("Copied public/ →", staticDir);
152
154
  }
153
155
 
154
- const iconFile = resolve(cwd, "app/icon.png");
155
- if (existsSync(iconFile)) {
156
+ const iconFile = findIconFile(resolve(cwd, "app"));
157
+ if (iconFile) {
156
158
  mkdirSync(staticDir, { recursive: true });
157
- cpSync(iconFile, resolve(staticDir, "icon.png"));
158
- console.log("Copied app/icon.png ", staticDir);
159
+ await copyAgentIcon(iconFile, resolve(staticDir, "icon.png"));
160
+ await generateFavicon(iconFile, resolve(staticDir, "favicon.ico"));
161
+ console.log("Copied app/icon →", staticDir);
159
162
  }
160
163
 
161
164
  // Log summary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aixyz/cli",
3
- "version": "0.5.2",
3
+ "version": "0.7.0",
4
4
  "description": "Payment-native SDK for AI Agent",
5
5
  "keywords": [
6
6
  "ai",
@@ -26,11 +26,12 @@
26
26
  "bin.ts"
27
27
  ],
28
28
  "dependencies": {
29
- "@aixyz/config": "0.5.2",
29
+ "@aixyz/config": "0.7.0",
30
30
  "@next/env": "^16.1.6",
31
31
  "boxen": "^8.0.0",
32
32
  "chalk": "^5.0.0",
33
- "commander": "^14.0.3"
33
+ "commander": "^14.0.3",
34
+ "sharp": "^0.34.5"
34
35
  },
35
36
  "engines": {
36
37
  "bun": ">=1.3.0"