@opentray/vite-plugin 0.18.0 → 0.19.1
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/index.d.mts +22 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +30 -15
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -15,10 +15,21 @@ interface OpenTrayAppIconOptions {
|
|
|
15
15
|
readonly implementationPath?: string;
|
|
16
16
|
/** Advanced: override the source file whose bytes identify the generator implementation. */
|
|
17
17
|
readonly implementationSourcePath?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Pre-composed source: skip glyph re-tiling; pass pixels through verbatim.
|
|
20
|
+
*/
|
|
21
|
+
readonly composed?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Separate macOS content source; ICNS encodes from this while ICO/Linux
|
|
24
|
+
* use sourcePath.
|
|
25
|
+
*/
|
|
26
|
+
readonly macosSourcePath?: string;
|
|
18
27
|
}
|
|
19
28
|
interface OpenTrayAppIconCacheMetadata {
|
|
20
29
|
readonly schemaVersion: number;
|
|
21
30
|
readonly sourceSha256: string;
|
|
31
|
+
readonly macosSourceSha256?: string;
|
|
32
|
+
readonly composed?: boolean;
|
|
22
33
|
readonly sourceImplementationSha256: string | null;
|
|
23
34
|
readonly implementationSha256: string;
|
|
24
35
|
readonly recipeVersion: string;
|
|
@@ -44,6 +55,17 @@ interface OpenTrayAppIconManifest {
|
|
|
44
55
|
interface OpenTrayAppIconPluginOptions {
|
|
45
56
|
/** Brand source image. This is intentionally explicit so the plugin is app-agnostic. */
|
|
46
57
|
readonly sourcePath: string;
|
|
58
|
+
/**
|
|
59
|
+
* Pre-composed source: the image already carries its background and
|
|
60
|
+
* squircle mask, so glyph re-tiling (trim → symbol → white tile) is
|
|
61
|
+
* skipped and the pixels pass through verbatim.
|
|
62
|
+
*/
|
|
63
|
+
readonly composed?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Separate macOS content source (e.g. the best-practice 824-in-1024
|
|
66
|
+
* variant): ICNS encodes from this while ICO/Linux use sourcePath.
|
|
67
|
+
*/
|
|
68
|
+
readonly macosSourcePath?: string;
|
|
47
69
|
readonly outputPath?: string;
|
|
48
70
|
readonly icnsOutputPath?: string;
|
|
49
71
|
readonly icoOutputPath?: string;
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/app-icon.ts","../src/index.ts"],"mappings":";;;;;UAmDiB,sBAAA;EAAA,SACN,UAAA;EAAA,SACA,UAAA;EAAA,SACA,cAAA;EAAA,SACA,aAAA;EAAA,SACA,oBAAA;EAAA,SACA,kBAAA;EAAA,SACA,SAAA;EALA;EAAA,SAOA,kBAAA;EALA;EAAA,SAOA,wBAAA;AAAA;AAAA,UAGM,4BAAA;EAAA,SACN,aAAA;EAAA,SACA,YAAA;EAAA,SACA,0BAAA;EAAA,SACA,oBAAA;EAAA,SACA,aAAA;EAAA,SACA,YAAA;EAAA,SACA,kBAAA;EAAA,SACA,oBAAA;EAAA,SACA,UAAA;EAAA,SACA,cAAA;EAAA,SACA,aAAA;EAAA,SACA,mBAAA;IAAA,SACE,IAAA;IAAA,SACA,IAAA;EAAA;EAAA,SAEF,kBAAA;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/app-icon.ts","../src/index.ts"],"mappings":";;;;;UAmDiB,sBAAA;EAAA,SACN,UAAA;EAAA,SACA,UAAA;EAAA,SACA,cAAA;EAAA,SACA,aAAA;EAAA,SACA,oBAAA;EAAA,SACA,kBAAA;EAAA,SACA,SAAA;EALA;EAAA,SAOA,kBAAA;EALA;EAAA,SAOA,wBAAA;EALA;;;EAAA,SASA,QAAA;EAAA;;;AAKe;EALf,SAKA,eAAA;AAAA;AAAA,UAGM,4BAAA;EAAA,SACN,aAAA;EAAA,SACA,YAAA;EAAA,SACA,iBAAA;EAAA,SACA,QAAA;EAAA,SACA,0BAAA;EAAA,SACA,oBAAA;EAAA,SACA,aAAA;EAAA,SACA,YAAA;EAAA,SACA,kBAAA;EAAA,SACA,oBAAA;EAAA,SACA,UAAA;EAAA,SACA,cAAA;EAAA,SACA,aAAA;EAAA,SACA,mBAAA;IAAA,SACE,IAAA;IAAA,SACA,IAAA;EAAA;EAAA,SAEF,kBAAA;EAEA;EAAA,SAAA,OAAA,EAAS,OAAO;AAAA;AAAA,UAGV,uBAAA;EAAA,SACN,aAAA;EAD6B;EAAA,SAG7B,OAAA,EAAS,OAAO;AAAA;AAAA,UAGV,4BAAA;EAHN;EAAA,SAKA,UAAA;EALgB;AAAA;AAG3B;;;EAH2B,SAWhB,QAAA;EANA;;;;EAAA,SAWA,eAAA;EAAA,SACA,UAAA;EAAA,SACA,cAAA;EAAA,SACA,aAAA;EAAA,SACA,oBAAA;EAAA,SACA,kBAAA;EAAA,SACA,SAAA;AAAA;;iBAIW,uBAAA,CACpB,OAAA,EAAS,sBAAA,GACR,OAAA,CAAQ,4BAAA;;iBA8DK,qBAAA,CACd,OAAA,EAAS,4BAAA,GACR,MAAM;;;UC5KQ,yBAAA;EAAA,SACN,GAAA,EAAK,oBAAA;EAAA,SACL,WAAA,EAAa,qBAAA;EAAA,SACb,eAAA,GAAkB,QAAA,CAAS,MAAA,SAAe,qBAAA;EAAA,SAC1C,eAAA,GAAkB,QAAA,CAAS,MAAA,SAAe,qBAAA;EAAA,SAC1C,KAAA;EAAA,SACA,YAAA;AAAA;AAAA,UAGM,sBAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,KAAA;IAAA,SACE,MAAA;EAAA;AAAA;AAAA,UAII,mBAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,QAAA;EAAA,SACA,cAAA;EAAA,SACA,IAAA;AAAA;AAAA,KAGC,cAAA,GAAiB,QAAQ,CAAC,MAAA;AAAA,UAErB,kBAAA;EAAA,SACN,IAAA;EAAA,SACA,KAAA;EACT,cAAA,CAAe,MAAA,EAAQ,sBAAA;EACvB,WAAA,CAAY,OAAA,WAAkB,MAAA,EAAQ,cAAA,GAAiB,OAAA;EAAA,SAC9C,aAAA,QAAqB,qBAAA;AAAA;AAAA,UAGf,kCAAA,SACP,IAAI,CAAC,sBAAA;EDyBJ;EAAA,SCvBA,UAAA;AAAA;AAAA,UAGM,2BAAA;EAAA,SACN,IAAA;EAAA,SACA,KAAA;EACT,cAAA,CAAe,MAAA,EAAQ,sBAAA;EACvB,WAAA,IAAe,OAAA;EAAA,SACN,aAAA,QAAqB,6BAAA;AAAA;;cAInB,uBAAA,GACX,OAAA,EAAS,kCAAA,KACR,2BAyBF;AAAA,cAEY,kBAAA,GAAsB,OAAA,EAAS,yBAAA,KAA4B,kBAiCvE;AAAA,cAEY,gBAAA,GAAoB,MAAsB,EAAd,cAAc"}
|
package/dist/index.mjs
CHANGED
|
@@ -90,6 +90,8 @@ async function generateOpenTrayAppIcon(options) {
|
|
|
90
90
|
const metadata = await createCacheMetadata({
|
|
91
91
|
sourcePath: options.sourcePath,
|
|
92
92
|
implementationPath,
|
|
93
|
+
...options.composed === true ? { composed: true } : {},
|
|
94
|
+
...options.macosSourcePath === void 0 ? {} : { macosSourcePath: options.macosSourcePath },
|
|
93
95
|
outputPath,
|
|
94
96
|
icnsOutputPath,
|
|
95
97
|
icoOutputPath,
|
|
@@ -98,13 +100,14 @@ async function generateOpenTrayAppIcon(options) {
|
|
|
98
100
|
...options.implementationSourcePath === void 0 ? {} : { implementationSourcePath: options.implementationSourcePath }
|
|
99
101
|
});
|
|
100
102
|
if (await cacheMatches(cachePath, metadata)) return metadata;
|
|
101
|
-
const rendered = await renderAppIcon(options.sourcePath);
|
|
103
|
+
const rendered = await renderAppIcon(options.sourcePath, options.composed === true);
|
|
104
|
+
const macosRendered = options.macosSourcePath === void 0 || options.macosSourcePath === options.sourcePath ? rendered : await renderAppIcon(options.macosSourcePath, options.composed === true);
|
|
102
105
|
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
|
103
106
|
await fs.mkdir(path.dirname(icnsOutputPath), { recursive: true });
|
|
104
107
|
await fs.mkdir(path.dirname(icoOutputPath), { recursive: true });
|
|
105
108
|
await fs.mkdir(path.dirname(cachePath), { recursive: true });
|
|
106
109
|
await fs.writeFile(outputPath, rendered);
|
|
107
|
-
await encodeNativeIcons(rendered, icnsOutputPath, icoOutputPath);
|
|
110
|
+
await encodeNativeIcons(rendered, macosRendered, icnsOutputPath, icoOutputPath);
|
|
108
111
|
await writeLinuxIcons(rendered, metadata.linuxPngOutputPaths);
|
|
109
112
|
await writeManifest(metadata);
|
|
110
113
|
await fs.writeFile(cachePath, `${JSON.stringify(metadata, null, 2)}\n`, "utf8");
|
|
@@ -125,6 +128,8 @@ function openTrayAppIconPlugin(options) {
|
|
|
125
128
|
const cachePath = options.cachePath ?? path.resolve(config.root, ".cache/app-icon.json");
|
|
126
129
|
generation ??= generateOpenTrayAppIcon({
|
|
127
130
|
sourcePath: path.resolve(options.sourcePath),
|
|
131
|
+
...options.composed === true ? { composed: true } : {},
|
|
132
|
+
...options.macosSourcePath === void 0 ? {} : { macosSourcePath: path.resolve(options.macosSourcePath) },
|
|
128
133
|
outputPath,
|
|
129
134
|
icnsOutputPath,
|
|
130
135
|
icoOutputPath,
|
|
@@ -174,6 +179,8 @@ async function createCacheMetadata(options) {
|
|
|
174
179
|
return {
|
|
175
180
|
schemaVersion: CACHE_SCHEMA_VERSION,
|
|
176
181
|
sourceSha256: await sha256(options.sourcePath),
|
|
182
|
+
...options.macosSourcePath === void 0 ? {} : { macosSourceSha256: await sha256(options.macosSourcePath) },
|
|
183
|
+
...options.composed === true ? { composed: true } : {},
|
|
177
184
|
sourceImplementationSha256: sourceImplementationPath === null ? null : await sha256(sourceImplementationPath),
|
|
178
185
|
implementationSha256: await sha256(options.implementationPath),
|
|
179
186
|
recipeVersion: RECIPE_VERSION,
|
|
@@ -188,7 +195,11 @@ async function createCacheMetadata(options) {
|
|
|
188
195
|
appIcon
|
|
189
196
|
};
|
|
190
197
|
}
|
|
191
|
-
async function renderAppIcon(sourcePath) {
|
|
198
|
+
async function renderAppIcon(sourcePath, composed = false) {
|
|
199
|
+
if (composed) return sharp(sourcePath, { failOn: "none" }).resize(ICON_SIZE, ICON_SIZE, {
|
|
200
|
+
fit: "contain",
|
|
201
|
+
kernel: sharp.kernel.lanczos3
|
|
202
|
+
}).withMetadata({ density: APP_ICON_DENSITY }).png({ compressionLevel: 9 }).toBuffer();
|
|
192
203
|
const symbol = await sharp(sourcePath).trim({ threshold: 0 }).resize(SYMBOL_SIZE, SYMBOL_SIZE, {
|
|
193
204
|
fit: "inside",
|
|
194
205
|
kernel: sharp.kernel.lanczos3
|
|
@@ -223,21 +234,25 @@ async function renderAppIcon(sourcePath) {
|
|
|
223
234
|
left: symbolLeft
|
|
224
235
|
}]).withMetadata({ density: APP_ICON_DENSITY }).png({ compressionLevel: 9 }).toBuffer();
|
|
225
236
|
}
|
|
226
|
-
async function encodeNativeIcons(rendered, icnsOutputPath, icoOutputPath) {
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
237
|
+
async function encodeNativeIcons(rendered, macosRendered, icnsOutputPath, icoOutputPath) {
|
|
238
|
+
const cacheFor = (source) => {
|
|
239
|
+
const bySize = /* @__PURE__ */ new Map();
|
|
240
|
+
return { async pngAt(size) {
|
|
241
|
+
const cached = bySize.get(size);
|
|
242
|
+
if (cached !== void 0) return cached;
|
|
243
|
+
const png = await sharp(source).resize(size, size, { fit: "contain" }).withMetadata({ density: APP_ICON_DENSITY }).png({ compressionLevel: 9 }).toBuffer();
|
|
244
|
+
bySize.set(size, png);
|
|
245
|
+
return png;
|
|
246
|
+
} };
|
|
234
247
|
};
|
|
248
|
+
const windows = cacheFor(rendered);
|
|
249
|
+
const macos = cacheFor(macosRendered);
|
|
235
250
|
const icns = new IconIcns();
|
|
236
251
|
icns.toc = true;
|
|
237
|
-
for (const { tag, size } of ICNS_REPRESENTATIONS) await icns.addFromPng(await pngAt(size), [tag], false);
|
|
252
|
+
for (const { tag, size } of ICNS_REPRESENTATIONS) await icns.addFromPng(await macos.pngAt(size), [tag], false);
|
|
238
253
|
await fs.writeFile(icnsOutputPath, icns.encode());
|
|
239
254
|
const ico = new IconIco();
|
|
240
|
-
for (const size of ICO_SIZES) await ico.addFromPng(await pngAt(size), null, false);
|
|
255
|
+
for (const size of ICO_SIZES) await ico.addFromPng(await windows.pngAt(size), null, false);
|
|
241
256
|
await fs.writeFile(icoOutputPath, ico.encode());
|
|
242
257
|
}
|
|
243
258
|
async function writeLinuxIcons(rendered, outputs) {
|
|
@@ -293,12 +308,12 @@ async function cacheMatches(file, expected) {
|
|
|
293
308
|
}
|
|
294
309
|
}
|
|
295
310
|
function sameCacheIdentity(actual, expected) {
|
|
296
|
-
return actual.schemaVersion === expected.schemaVersion && actual.sourceSha256 === expected.sourceSha256 && actual.sourceImplementationSha256 === expected.sourceImplementationSha256 && actual.implementationSha256 === expected.implementationSha256 && actual.recipeVersion === expected.recipeVersion && actual.sharpVersion === expected.sharpVersion && actual.iconEncoderVersion === expected.iconEncoderVersion && actual.figmaSquircleVersion === expected.figmaSquircleVersion && actual.outputPath === expected.outputPath && actual.icnsOutputPath === expected.icnsOutputPath && actual.icoOutputPath === expected.icoOutputPath && actual.manifestOutputPath === expected.manifestOutputPath && JSON.stringify(actual.linuxPngOutputPaths) === JSON.stringify(expected.linuxPngOutputPaths) && JSON.stringify(actual.appIcon) === JSON.stringify(expected.appIcon);
|
|
311
|
+
return actual.schemaVersion === expected.schemaVersion && actual.sourceSha256 === expected.sourceSha256 && actual.macosSourceSha256 === expected.macosSourceSha256 && actual.composed === expected.composed && actual.sourceImplementationSha256 === expected.sourceImplementationSha256 && actual.implementationSha256 === expected.implementationSha256 && actual.recipeVersion === expected.recipeVersion && actual.sharpVersion === expected.sharpVersion && actual.iconEncoderVersion === expected.iconEncoderVersion && actual.figmaSquircleVersion === expected.figmaSquircleVersion && actual.outputPath === expected.outputPath && actual.icnsOutputPath === expected.icnsOutputPath && actual.icoOutputPath === expected.icoOutputPath && actual.manifestOutputPath === expected.manifestOutputPath && JSON.stringify(actual.linuxPngOutputPaths) === JSON.stringify(expected.linuxPngOutputPaths) && JSON.stringify(actual.appIcon) === JSON.stringify(expected.appIcon);
|
|
297
312
|
}
|
|
298
313
|
function isCacheMetadata(value) {
|
|
299
314
|
if (typeof value !== "object" || value === null) return false;
|
|
300
315
|
const record = value;
|
|
301
|
-
return typeof record.schemaVersion === "number" && typeof record.sourceSha256 === "string" && (record.sourceImplementationSha256 === null || typeof record.sourceImplementationSha256 === "string") && typeof record.implementationSha256 === "string" && typeof record.recipeVersion === "string" && typeof record.sharpVersion === "string" && typeof record.iconEncoderVersion === "string" && typeof record.figmaSquircleVersion === "string" && typeof record.outputPath === "string" && typeof record.icnsOutputPath === "string" && typeof record.icoOutputPath === "string" && Array.isArray(record.linuxPngOutputPaths) && typeof record.manifestOutputPath === "string" && Array.isArray(record.appIcon);
|
|
316
|
+
return typeof record.schemaVersion === "number" && typeof record.sourceSha256 === "string" && (record.macosSourceSha256 === void 0 || typeof record.macosSourceSha256 === "string") && (record.composed === void 0 || typeof record.composed === "boolean") && (record.sourceImplementationSha256 === null || typeof record.sourceImplementationSha256 === "string") && typeof record.implementationSha256 === "string" && typeof record.recipeVersion === "string" && typeof record.sharpVersion === "string" && typeof record.iconEncoderVersion === "string" && typeof record.figmaSquircleVersion === "string" && typeof record.outputPath === "string" && typeof record.icnsOutputPath === "string" && typeof record.icoOutputPath === "string" && Array.isArray(record.linuxPngOutputPaths) && typeof record.manifestOutputPath === "string" && Array.isArray(record.appIcon);
|
|
302
317
|
}
|
|
303
318
|
async function resolveSourceImplementationPath(implementationPath) {
|
|
304
319
|
if (implementationPath.endsWith(`${path.sep}src${path.sep}app-icon.ts`)) return implementationPath;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/app-icon.ts","../src/index.ts"],"sourcesContent":["// Orthogonal intents (maintained 2026-07-20; original user request: move the\n// skill-creator-v2 app-icon build chain into OpenTray's Vite plugin):\n// 1. Normalize a brand source image into a readable application icon with a\n// white safe-area tile and a transparent outer margin.\n// 2. Produce standard macOS ICNS, Windows ICO, and Linux theme PNG assets.\n// 3. Cache the output by source, source implementation, bundled implementation,\n// recipe, encoder, and output identity so stale generated assets cannot leak\n// into a dev runtime.\n// Compromise: published packages do not ship TypeScript sources, so their cache\n// uses a null source hash and the bundled plugin hash as the implementation\n// authority; linked consumers hash both layers.\n\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { getSvgPath } from \"figma-squircle\";\nimport sharp from \"sharp\";\nimport type { Plugin } from \"vite\";\n\nimport type { AppIcon } from \"@opentray/spec\";\nimport { IconIcns, IconIco } from \"@shockpkg/icon-encoder\";\n\nconst ICON_SIZE = 1024;\nconst TILE_INSET = 64;\nconst TILE_SIZE = ICON_SIZE - TILE_INSET * 2;\nconst TILE_RADIUS = 196;\nconst TILE_SMOOTHING = 1;\nconst SYMBOL_SIZE = 704;\nconst APP_ICON_DENSITY = 72;\nconst CACHE_SCHEMA_VERSION = 6;\nconst RECIPE_VERSION = `squircle-v3:${ICON_SIZE}:${TILE_INSET}:${TILE_RADIUS}:${TILE_SMOOTHING}:${SYMBOL_SIZE}:${APP_ICON_DENSITY}dpi:icns-tagged`;\nconst ICO_SIZES = [16, 24, 32, 48, 64, 128, 256] as const;\nconst LINUX_SIZES = [16, 32, 48, 64, 128, 256, 512] as const;\nconst ICNS_REPRESENTATIONS = [\n { tag: \"ic12\", size: 64 },\n { tag: \"ic07\", size: 128 },\n { tag: \"ic13\", size: 256 },\n { tag: \"ic08\", size: 256 },\n { tag: \"ic04\", size: 16 },\n { tag: \"ic14\", size: 512 },\n { tag: \"ic09\", size: 512 },\n { tag: \"ic05\", size: 32 },\n { tag: \"ic10\", size: 1024 },\n { tag: \"ic11\", size: 32 },\n] as const;\n\nconst require = createRequire(import.meta.url);\n\nexport interface OpenTrayAppIconOptions {\n readonly sourcePath: string;\n readonly outputPath?: string;\n readonly icnsOutputPath?: string;\n readonly icoOutputPath?: string;\n readonly linuxOutputDirectory?: string;\n readonly manifestOutputPath?: string;\n readonly cachePath?: string;\n /** Advanced: override the module whose bytes identify the generator implementation. */\n readonly implementationPath?: string;\n /** Advanced: override the source file whose bytes identify the generator implementation. */\n readonly implementationSourcePath?: string;\n}\n\nexport interface OpenTrayAppIconCacheMetadata {\n readonly schemaVersion: number;\n readonly sourceSha256: string;\n readonly sourceImplementationSha256: string | null;\n readonly implementationSha256: string;\n readonly recipeVersion: string;\n readonly sharpVersion: string;\n readonly iconEncoderVersion: string;\n readonly figmaSquircleVersion: string;\n readonly outputPath: string;\n readonly icnsOutputPath: string;\n readonly icoOutputPath: string;\n readonly linuxPngOutputPaths: readonly {\n readonly size: number;\n readonly path: string;\n }[];\n readonly manifestOutputPath: string;\n /** Absolute file sources ready to pass to OpenTray at runtime. */\n readonly appIcon: AppIcon;\n}\n\nexport interface OpenTrayAppIconManifest {\n readonly schemaVersion: 1;\n /** File paths are relative to the manifest file. */\n readonly appIcon: AppIcon;\n}\n\nexport interface OpenTrayAppIconPluginOptions {\n /** Brand source image. This is intentionally explicit so the plugin is app-agnostic. */\n readonly sourcePath: string;\n readonly outputPath?: string;\n readonly icnsOutputPath?: string;\n readonly icoOutputPath?: string;\n readonly linuxOutputDirectory?: string;\n readonly manifestOutputPath?: string;\n readonly cachePath?: string;\n}\n\n/** Generate one strict cross-platform AppIcon asset set. */\nexport async function generateOpenTrayAppIcon(\n options: OpenTrayAppIconOptions\n): Promise<OpenTrayAppIconCacheMetadata> {\n const outputPath =\n options.outputPath ??\n path.join(path.dirname(options.sourcePath), \"app-icon.png\");\n const icnsOutputPath =\n options.icnsOutputPath ??\n path.join(path.dirname(outputPath), \"app-icon.icns\");\n const icoOutputPath =\n options.icoOutputPath ??\n path.join(path.dirname(outputPath), \"app-icon.ico\");\n const linuxOutputDirectory =\n options.linuxOutputDirectory ??\n path.join(path.dirname(outputPath), \"linux\");\n const manifestOutputPath =\n options.manifestOutputPath ??\n path.join(path.dirname(outputPath), \"app-icon.json\");\n const cachePath =\n options.cachePath ??\n path.join(path.dirname(outputPath), \"../../.cache/app-icon.json\");\n const implementationPath =\n options.implementationPath ?? fileURLToPath(import.meta.url);\n const metadata = await createCacheMetadata({\n sourcePath: options.sourcePath,\n implementationPath,\n outputPath,\n icnsOutputPath,\n icoOutputPath,\n linuxOutputDirectory,\n manifestOutputPath,\n ...(options.implementationSourcePath === undefined\n ? {}\n : { implementationSourcePath: options.implementationSourcePath }),\n });\n\n if (await cacheMatches(cachePath, metadata)) return metadata;\n\n const rendered = await renderAppIcon(options.sourcePath);\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.mkdir(path.dirname(icnsOutputPath), { recursive: true });\n await fs.mkdir(path.dirname(icoOutputPath), { recursive: true });\n await fs.mkdir(path.dirname(cachePath), { recursive: true });\n await fs.writeFile(outputPath, rendered);\n await encodeNativeIcons(rendered, icnsOutputPath, icoOutputPath);\n await writeLinuxIcons(rendered, metadata.linuxPngOutputPaths);\n await writeManifest(metadata);\n await fs.writeFile(\n cachePath,\n `${JSON.stringify(metadata, null, 2)}\\n`,\n \"utf8\"\n );\n return metadata;\n}\n\n/** Create the Vite plugin used by both serve and build modes. */\nexport function openTrayAppIconPlugin(\n options: OpenTrayAppIconPluginOptions\n): Plugin {\n let generation: Promise<OpenTrayAppIconCacheMetadata> | undefined;\n\n return {\n name: \"opentray/app-icon\",\n enforce: \"pre\",\n async configResolved(config) {\n const outputPath =\n options.outputPath ??\n path.resolve(config.root, \"static/icons/app-icon.png\");\n const icnsOutputPath =\n options.icnsOutputPath ??\n path.resolve(config.root, \"static/icons/app-icon.icns\");\n const icoOutputPath =\n options.icoOutputPath ??\n path.resolve(config.root, \"static/icons/app-icon.ico\");\n const linuxOutputDirectory =\n options.linuxOutputDirectory ??\n path.resolve(config.root, \"static/icons/linux\");\n const manifestOutputPath =\n options.manifestOutputPath ??\n path.resolve(config.root, \"static/icons/app-icon.json\");\n const cachePath =\n options.cachePath ?? path.resolve(config.root, \".cache/app-icon.json\");\n generation ??= generateOpenTrayAppIcon({\n sourcePath: path.resolve(options.sourcePath),\n outputPath,\n icnsOutputPath,\n icoOutputPath,\n linuxOutputDirectory,\n manifestOutputPath,\n cachePath,\n });\n await generation;\n },\n };\n}\n\nasync function createCacheMetadata(options: {\n sourcePath: string;\n implementationPath: string;\n implementationSourcePath?: string;\n outputPath: string;\n icnsOutputPath: string;\n icoOutputPath: string;\n linuxOutputDirectory: string;\n manifestOutputPath: string;\n}): Promise<OpenTrayAppIconCacheMetadata> {\n const sourceImplementationPath =\n options.implementationSourcePath ??\n (await resolveSourceImplementationPath(options.implementationPath));\n const linuxPngOutputPaths = LINUX_SIZES.map((size) => ({\n size,\n path: path.resolve(\n options.linuxOutputDirectory,\n `${size}x${size}`,\n \"app-icon.png\"\n ),\n }));\n const icnsOutputPath = path.resolve(options.icnsOutputPath);\n const icoOutputPath = path.resolve(options.icoOutputPath);\n const appIcon: AppIcon = [\n {\n platform: \"darwin\",\n format: \"icns\",\n source: { type: \"file\", path: icnsOutputPath },\n },\n {\n platform: \"windows\",\n format: \"ico\",\n source: { type: \"file\", path: icoOutputPath },\n },\n ...linuxPngOutputPaths.map(({ size, path: pngPath }) => ({\n platform: \"linux\" as const,\n format: \"png\" as const,\n size,\n source: { type: \"file\" as const, path: pngPath },\n })),\n ];\n return {\n schemaVersion: CACHE_SCHEMA_VERSION,\n sourceSha256: await sha256(options.sourcePath),\n sourceImplementationSha256:\n sourceImplementationPath === null\n ? null\n : await sha256(sourceImplementationPath),\n implementationSha256: await sha256(options.implementationPath),\n recipeVersion: RECIPE_VERSION,\n sharpVersion: await packageVersion(\"sharp\"),\n iconEncoderVersion: await packageVersion(\"@shockpkg/icon-encoder\"),\n figmaSquircleVersion: await packageVersion(\"figma-squircle\"),\n outputPath: path.resolve(options.outputPath),\n icnsOutputPath,\n icoOutputPath,\n linuxPngOutputPaths,\n manifestOutputPath: path.resolve(options.manifestOutputPath),\n appIcon,\n };\n}\n\nasync function renderAppIcon(sourcePath: string): Promise<Buffer> {\n const symbol = await sharp(sourcePath)\n .trim({ threshold: 0 })\n .resize(SYMBOL_SIZE, SYMBOL_SIZE, {\n fit: \"inside\",\n kernel: sharp.kernel.lanczos3,\n })\n .png()\n .toBuffer({ resolveWithObject: true });\n const symbolLeft = Math.round((ICON_SIZE - symbol.info.width) / 2);\n const symbolTop = Math.round((ICON_SIZE - symbol.info.height) / 2);\n const squirclePath = getSvgPath({\n width: TILE_SIZE,\n height: TILE_SIZE,\n cornerRadius: TILE_RADIUS,\n cornerSmoothing: TILE_SMOOTHING,\n preserveSmoothing: true,\n });\n const whiteTile = Buffer.from(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${TILE_SIZE}\" height=\"${TILE_SIZE}\"><path d=\"${squirclePath}\" fill=\"#fff\"/></svg>`\n );\n return sharp({\n create: {\n width: ICON_SIZE,\n height: ICON_SIZE,\n channels: 4,\n background: { r: 0, g: 0, b: 0, alpha: 0 },\n },\n })\n .composite([\n { input: whiteTile, top: TILE_INSET, left: TILE_INSET },\n { input: symbol.data, top: symbolTop, left: symbolLeft },\n ])\n .withMetadata({ density: APP_ICON_DENSITY })\n .png({ compressionLevel: 9 })\n .toBuffer();\n}\n\nasync function encodeNativeIcons(\n rendered: Buffer,\n icnsOutputPath: string,\n icoOutputPath: string\n): Promise<void> {\n const pngBySize = new Map<number, Buffer>();\n const pngAt = async (size: number): Promise<Buffer> => {\n const cached = pngBySize.get(size);\n if (cached !== undefined) return cached;\n const png = await sharp(rendered)\n .resize(size, size, { fit: \"contain\" })\n .withMetadata({ density: APP_ICON_DENSITY })\n .png({ compressionLevel: 9 })\n .toBuffer();\n pngBySize.set(size, png);\n return png;\n };\n\n const icns = new IconIcns();\n icns.toc = true;\n for (const { tag, size } of ICNS_REPRESENTATIONS) {\n await icns.addFromPng(await pngAt(size), [tag], false);\n }\n await fs.writeFile(icnsOutputPath, icns.encode());\n\n const ico = new IconIco();\n for (const size of ICO_SIZES) {\n await ico.addFromPng(await pngAt(size), null, false);\n }\n await fs.writeFile(icoOutputPath, ico.encode());\n}\n\nasync function writeLinuxIcons(\n rendered: Buffer,\n outputs: OpenTrayAppIconCacheMetadata[\"linuxPngOutputPaths\"]\n): Promise<void> {\n await Promise.all(\n outputs.map(async ({ size, path: outputPath }) => {\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await sharp(rendered)\n .resize(size, size, { fit: \"contain\" })\n .withMetadata({ density: APP_ICON_DENSITY })\n .png({ compressionLevel: 9 })\n .toFile(outputPath);\n })\n );\n}\n\nasync function writeManifest(\n metadata: OpenTrayAppIconCacheMetadata\n): Promise<void> {\n const manifestDirectory = path.dirname(metadata.manifestOutputPath);\n const relativeSource = (\n sourcePath: string\n ): { type: \"file\"; path: string } => ({\n type: \"file\",\n path: path\n .relative(manifestDirectory, sourcePath)\n .split(path.sep)\n .join(\"/\"),\n });\n const manifest: OpenTrayAppIconManifest = {\n schemaVersion: 1,\n appIcon: [\n {\n platform: \"darwin\",\n format: \"icns\",\n source: relativeSource(metadata.icnsOutputPath),\n },\n {\n platform: \"windows\",\n format: \"ico\",\n source: relativeSource(metadata.icoOutputPath),\n },\n ...metadata.linuxPngOutputPaths.map(({ size, path: pngPath }) => ({\n platform: \"linux\" as const,\n format: \"png\" as const,\n size,\n source: relativeSource(pngPath),\n })),\n ],\n };\n await fs.mkdir(manifestDirectory, { recursive: true });\n await fs.writeFile(\n metadata.manifestOutputPath,\n `${JSON.stringify(manifest, null, 2)}\\n`\n );\n}\n\nasync function cacheMatches(\n file: string,\n expected: OpenTrayAppIconCacheMetadata\n): Promise<boolean> {\n try {\n const parsed: unknown = JSON.parse(await fs.readFile(file, \"utf8\"));\n if (!isCacheMetadata(parsed) || !sameCacheIdentity(parsed, expected))\n return false;\n await Promise.all([\n fs.access(expected.outputPath),\n fs.access(expected.icnsOutputPath),\n fs.access(expected.icoOutputPath),\n fs.access(expected.manifestOutputPath),\n ...expected.linuxPngOutputPaths.map(({ path: outputPath }) =>\n fs.access(outputPath)\n ),\n ]);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction sameCacheIdentity(\n actual: OpenTrayAppIconCacheMetadata,\n expected: OpenTrayAppIconCacheMetadata\n): boolean {\n return (\n actual.schemaVersion === expected.schemaVersion &&\n actual.sourceSha256 === expected.sourceSha256 &&\n actual.sourceImplementationSha256 === expected.sourceImplementationSha256 &&\n actual.implementationSha256 === expected.implementationSha256 &&\n actual.recipeVersion === expected.recipeVersion &&\n actual.sharpVersion === expected.sharpVersion &&\n actual.iconEncoderVersion === expected.iconEncoderVersion &&\n actual.figmaSquircleVersion === expected.figmaSquircleVersion &&\n actual.outputPath === expected.outputPath &&\n actual.icnsOutputPath === expected.icnsOutputPath &&\n actual.icoOutputPath === expected.icoOutputPath &&\n actual.manifestOutputPath === expected.manifestOutputPath &&\n JSON.stringify(actual.linuxPngOutputPaths) ===\n JSON.stringify(expected.linuxPngOutputPaths) &&\n JSON.stringify(actual.appIcon) === JSON.stringify(expected.appIcon)\n );\n}\n\nfunction isCacheMetadata(\n value: unknown\n): value is OpenTrayAppIconCacheMetadata {\n if (typeof value !== \"object\" || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n typeof record.schemaVersion === \"number\" &&\n typeof record.sourceSha256 === \"string\" &&\n (record.sourceImplementationSha256 === null ||\n typeof record.sourceImplementationSha256 === \"string\") &&\n typeof record.implementationSha256 === \"string\" &&\n typeof record.recipeVersion === \"string\" &&\n typeof record.sharpVersion === \"string\" &&\n typeof record.iconEncoderVersion === \"string\" &&\n typeof record.figmaSquircleVersion === \"string\" &&\n typeof record.outputPath === \"string\" &&\n typeof record.icnsOutputPath === \"string\" &&\n typeof record.icoOutputPath === \"string\" &&\n Array.isArray(record.linuxPngOutputPaths) &&\n typeof record.manifestOutputPath === \"string\" &&\n Array.isArray(record.appIcon)\n );\n}\n\nasync function resolveSourceImplementationPath(\n implementationPath: string\n): Promise<string | null> {\n if (implementationPath.endsWith(`${path.sep}src${path.sep}app-icon.ts`)) {\n return implementationPath;\n }\n const candidate = path.join(\n path.dirname(path.dirname(implementationPath)),\n \"src\",\n \"app-icon.ts\"\n );\n try {\n await fs.access(candidate);\n return candidate;\n } catch {\n return null;\n }\n}\n\nasync function packageVersion(packageName: string): Promise<string> {\n const entryPath = require.resolve(packageName);\n let directory = path.dirname(entryPath);\n while (true) {\n const packagePath = path.join(directory, \"package.json\");\n try {\n const parsed: unknown = JSON.parse(\n await fs.readFile(packagePath, \"utf8\")\n );\n if (isPackageMetadata(parsed, packageName)) return parsed.version;\n } catch {\n // Continue towards the package root; package exports may hide package.json.\n }\n const parent = path.dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n throw new Error(`Unable to resolve ${packageName} package version`);\n}\n\nfunction isPackageMetadata(\n value: unknown,\n packageName: string\n): value is { name: string; version: string } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"name\" in value &&\n value.name === packageName &&\n \"version\" in value &&\n typeof value.version === \"string\"\n );\n}\n\nasync function sha256(file: string): Promise<string> {\n return crypto\n .createHash(\"sha256\")\n .update(await fs.readFile(file))\n .digest(\"hex\");\n}\n","// Orthogonal intents (maintained 2026-07-20; original user request: expose the\n// OpenTray Vite packaging adapter and move skill-creator-v2 app-icon generation into it):\n// 1. Stage Vite bundle metadata and native runtime artifacts through one adapter.\n// 2. Re-export the app-icon generator without coupling the packaging contract to a consumer.\n// Compromise: both exports share the package entrypoint because Vite resolves one public adapter\n// module and the icon plugin has no runtime dependency on the artifact manifest.\n\nimport { resolve } from \"node:path\";\n\nimport {\n buildDarwinAppBundle,\n stageOpenTrayPackage,\n type DarwinAppBundleOptions,\n type OpenTrayArtifactInput,\n type OpenTrayPackagingApp,\n type OpenTrayPackageManifest,\n type OpenTrayPackageResult,\n type OpenTrayDarwinAppBundleResult,\n} from \"@opentray/packaging\";\n\nexport interface OpenTrayVitePluginOptions {\n readonly app: OpenTrayPackagingApp;\n readonly runtimeHost: OpenTrayArtifactInput;\n readonly nativeArtifacts?: Readonly<Record<string, OpenTrayArtifactInput>>;\n readonly companionAssets?: Readonly<Record<string, OpenTrayArtifactInput>>;\n readonly entry?: string;\n readonly manifestPath?: string;\n}\n\nexport interface ViteResolvedConfigLike {\n readonly root: string;\n readonly mode: string;\n readonly build: {\n readonly outDir: string;\n };\n}\n\nexport interface ViteOutputChunkLike {\n readonly type?: string;\n readonly isEntry?: boolean;\n readonly fileName?: string;\n readonly facadeModuleId?: string | null;\n readonly name?: string;\n}\n\nexport type ViteBundleLike = Readonly<Record<string, unknown>>;\n\nexport interface OpenTrayVitePlugin {\n readonly name: \"opentray-packaging\";\n readonly apply: \"build\";\n configResolved(config: ViteResolvedConfigLike): void;\n writeBundle(options: unknown, bundle: ViteBundleLike): Promise<void>;\n readonly getLastResult: () => OpenTrayPackageResult | undefined;\n}\n\nexport interface OpenTrayViteAppBundlePluginOptions\n extends Omit<DarwinAppBundleOptions, \"bundlePath\" | \"reinitialize\"> {\n /** Optional output path. Defaults to `<vite outDir>/<appName>.app`. */\n readonly bundlePath?: string;\n}\n\nexport interface OpenTrayViteAppBundlePlugin {\n readonly name: \"opentray-app-bundle\";\n readonly apply: \"build\";\n configResolved(config: ViteResolvedConfigLike): void;\n writeBundle(): Promise<void>;\n readonly getLastResult: () => OpenTrayDarwinAppBundleResult | undefined;\n}\n\n/** Vite lifecycle adapter for the shared Darwin app bundle contract. */\nexport const openTrayAppBundlePlugin = (\n options: OpenTrayViteAppBundlePluginOptions,\n): OpenTrayViteAppBundlePlugin => {\n let config: ViteResolvedConfigLike | undefined;\n let lastResult: OpenTrayDarwinAppBundleResult | undefined;\n return {\n name: \"opentray-app-bundle\",\n apply: \"build\",\n configResolved(resolvedConfig) {\n config = resolvedConfig;\n },\n async writeBundle() {\n const resolvedConfig = config ?? {\n root: process.cwd(),\n mode: \"production\",\n build: { outDir: \"dist\" },\n };\n const bundlePath =\n options.bundlePath ?? resolve(\n resolvedConfig.root,\n resolvedConfig.build.outDir,\n `${options.appName}.app`,\n );\n lastResult = await buildDarwinAppBundle({ ...options, bundlePath });\n },\n getLastResult: () => lastResult,\n };\n};\n\nexport const openTrayVitePlugin = (options: OpenTrayVitePluginOptions): OpenTrayVitePlugin => {\n let config: ViteResolvedConfigLike | undefined;\n let lastResult: OpenTrayPackageResult | undefined;\n\n return {\n name: \"opentray-packaging\",\n apply: \"build\",\n configResolved(resolvedConfig) {\n config = resolvedConfig;\n },\n async writeBundle(_options, bundle) {\n const resolvedConfig = config ?? {\n root: process.cwd(),\n mode: \"production\",\n build: { outDir: \"dist\" },\n };\n lastResult = await stageOpenTrayPackage({\n app: options.app,\n outDir: resolve(resolvedConfig.root, resolvedConfig.build.outDir),\n entry: options.entry ?? resolveViteEntry(bundle),\n adapter: { name: \"vite\", mode: resolvedConfig.mode },\n runtimeHost: options.runtimeHost,\n ...(options.nativeArtifacts === undefined\n ? {}\n : { nativeArtifacts: options.nativeArtifacts }),\n ...(options.companionAssets === undefined\n ? {}\n : { companionAssets: options.companionAssets }),\n ...(options.manifestPath === undefined ? {} : { manifestPath: options.manifestPath }),\n });\n },\n getLastResult: () => lastResult,\n };\n};\n\nexport const resolveViteEntry = (bundle: ViteBundleLike): string => {\n const entry = Object.values(bundle)\n .map(asOutputChunk)\n .find((chunk): chunk is ViteOutputChunkLike => chunk?.isEntry === true);\n const identity = entry?.facadeModuleId ?? entry?.fileName ?? entry?.name;\n if (identity === undefined || identity.length === 0) {\n throw new Error(\"OpenTray Vite packaging requires a Vite entry chunk or explicit entry option\");\n }\n return identity;\n};\n\nconst asOutputChunk = (value: unknown): ViteOutputChunkLike | undefined => {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n const record = value as Record<string, unknown>;\n return {\n ...(record.type === \"chunk\" ? { type: \"chunk\" } : {}),\n ...(typeof record.isEntry === \"boolean\" ? { isEntry: record.isEntry } : {}),\n ...(typeof record.fileName === \"string\" ? { fileName: record.fileName } : {}),\n ...(typeof record.facadeModuleId === \"string\" || record.facadeModuleId === null\n ? { facadeModuleId: record.facadeModuleId }\n : {}),\n ...(typeof record.name === \"string\" ? { name: record.name } : {}),\n };\n};\n\nexport type { OpenTrayPackageManifest, OpenTrayPackageResult };\n\nexport {\n generateOpenTrayAppIcon,\n openTrayAppIconPlugin,\n type OpenTrayAppIconCacheMetadata,\n type OpenTrayAppIconManifest,\n type OpenTrayAppIconOptions,\n type OpenTrayAppIconPluginOptions,\n} from \"./app-icon\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/app-icon.ts","../src/index.ts"],"sourcesContent":["// Orthogonal intents (maintained 2026-07-20; original user request: move the\n// skill-creator-v2 app-icon build chain into OpenTray's Vite plugin):\n// 1. Normalize a brand source image into a readable application icon with a\n// white safe-area tile and a transparent outer margin.\n// 2. Produce standard macOS ICNS, Windows ICO, and Linux theme PNG assets.\n// 3. Cache the output by source, source implementation, bundled implementation,\n// recipe, encoder, and output identity so stale generated assets cannot leak\n// into a dev runtime.\n// Compromise: published packages do not ship TypeScript sources, so their cache\n// uses a null source hash and the bundled plugin hash as the implementation\n// authority; linked consumers hash both layers.\n\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { getSvgPath } from \"figma-squircle\";\nimport sharp from \"sharp\";\nimport type { Plugin } from \"vite\";\n\nimport type { AppIcon } from \"@opentray/spec\";\nimport { IconIcns, IconIco } from \"@shockpkg/icon-encoder\";\n\nconst ICON_SIZE = 1024;\nconst TILE_INSET = 64;\nconst TILE_SIZE = ICON_SIZE - TILE_INSET * 2;\nconst TILE_RADIUS = 196;\nconst TILE_SMOOTHING = 1;\nconst SYMBOL_SIZE = 704;\nconst APP_ICON_DENSITY = 72;\nconst CACHE_SCHEMA_VERSION = 6;\nconst RECIPE_VERSION = `squircle-v3:${ICON_SIZE}:${TILE_INSET}:${TILE_RADIUS}:${TILE_SMOOTHING}:${SYMBOL_SIZE}:${APP_ICON_DENSITY}dpi:icns-tagged`;\nconst ICO_SIZES = [16, 24, 32, 48, 64, 128, 256] as const;\nconst LINUX_SIZES = [16, 32, 48, 64, 128, 256, 512] as const;\nconst ICNS_REPRESENTATIONS = [\n { tag: \"ic12\", size: 64 },\n { tag: \"ic07\", size: 128 },\n { tag: \"ic13\", size: 256 },\n { tag: \"ic08\", size: 256 },\n { tag: \"ic04\", size: 16 },\n { tag: \"ic14\", size: 512 },\n { tag: \"ic09\", size: 512 },\n { tag: \"ic05\", size: 32 },\n { tag: \"ic10\", size: 1024 },\n { tag: \"ic11\", size: 32 },\n] as const;\n\nconst require = createRequire(import.meta.url);\n\nexport interface OpenTrayAppIconOptions {\n readonly sourcePath: string;\n readonly outputPath?: string;\n readonly icnsOutputPath?: string;\n readonly icoOutputPath?: string;\n readonly linuxOutputDirectory?: string;\n readonly manifestOutputPath?: string;\n readonly cachePath?: string;\n /** Advanced: override the module whose bytes identify the generator implementation. */\n readonly implementationPath?: string;\n /** Advanced: override the source file whose bytes identify the generator implementation. */\n readonly implementationSourcePath?: string;\n /**\n * Pre-composed source: skip glyph re-tiling; pass pixels through verbatim.\n */\n readonly composed?: boolean;\n /**\n * Separate macOS content source; ICNS encodes from this while ICO/Linux\n * use sourcePath.\n */\n readonly macosSourcePath?: string;\n}\n\nexport interface OpenTrayAppIconCacheMetadata {\n readonly schemaVersion: number;\n readonly sourceSha256: string;\n readonly macosSourceSha256?: string;\n readonly composed?: boolean;\n readonly sourceImplementationSha256: string | null;\n readonly implementationSha256: string;\n readonly recipeVersion: string;\n readonly sharpVersion: string;\n readonly iconEncoderVersion: string;\n readonly figmaSquircleVersion: string;\n readonly outputPath: string;\n readonly icnsOutputPath: string;\n readonly icoOutputPath: string;\n readonly linuxPngOutputPaths: readonly {\n readonly size: number;\n readonly path: string;\n }[];\n readonly manifestOutputPath: string;\n /** Absolute file sources ready to pass to OpenTray at runtime. */\n readonly appIcon: AppIcon;\n}\n\nexport interface OpenTrayAppIconManifest {\n readonly schemaVersion: 1;\n /** File paths are relative to the manifest file. */\n readonly appIcon: AppIcon;\n}\n\nexport interface OpenTrayAppIconPluginOptions {\n /** Brand source image. This is intentionally explicit so the plugin is app-agnostic. */\n readonly sourcePath: string;\n /**\n * Pre-composed source: the image already carries its background and\n * squircle mask, so glyph re-tiling (trim → symbol → white tile) is\n * skipped and the pixels pass through verbatim.\n */\n readonly composed?: boolean;\n /**\n * Separate macOS content source (e.g. the best-practice 824-in-1024\n * variant): ICNS encodes from this while ICO/Linux use sourcePath.\n */\n readonly macosSourcePath?: string;\n readonly outputPath?: string;\n readonly icnsOutputPath?: string;\n readonly icoOutputPath?: string;\n readonly linuxOutputDirectory?: string;\n readonly manifestOutputPath?: string;\n readonly cachePath?: string;\n}\n\n/** Generate one strict cross-platform AppIcon asset set. */\nexport async function generateOpenTrayAppIcon(\n options: OpenTrayAppIconOptions\n): Promise<OpenTrayAppIconCacheMetadata> {\n const outputPath =\n options.outputPath ??\n path.join(path.dirname(options.sourcePath), \"app-icon.png\");\n const icnsOutputPath =\n options.icnsOutputPath ??\n path.join(path.dirname(outputPath), \"app-icon.icns\");\n const icoOutputPath =\n options.icoOutputPath ??\n path.join(path.dirname(outputPath), \"app-icon.ico\");\n const linuxOutputDirectory =\n options.linuxOutputDirectory ??\n path.join(path.dirname(outputPath), \"linux\");\n const manifestOutputPath =\n options.manifestOutputPath ??\n path.join(path.dirname(outputPath), \"app-icon.json\");\n const cachePath =\n options.cachePath ??\n path.join(path.dirname(outputPath), \"../../.cache/app-icon.json\");\n const implementationPath =\n options.implementationPath ?? fileURLToPath(import.meta.url);\n const metadata = await createCacheMetadata({\n sourcePath: options.sourcePath,\n implementationPath,\n ...(options.composed === true ? { composed: true } : {}),\n ...(options.macosSourcePath === undefined\n ? {}\n : { macosSourcePath: options.macosSourcePath }),\n outputPath,\n icnsOutputPath,\n icoOutputPath,\n linuxOutputDirectory,\n manifestOutputPath,\n ...(options.implementationSourcePath === undefined\n ? {}\n : { implementationSourcePath: options.implementationSourcePath }),\n });\n\n if (await cacheMatches(cachePath, metadata)) return metadata;\n\n const rendered = await renderAppIcon(options.sourcePath, options.composed === true);\n const macosRendered =\n options.macosSourcePath === undefined || options.macosSourcePath === options.sourcePath\n ? rendered\n : await renderAppIcon(options.macosSourcePath, options.composed === true);\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.mkdir(path.dirname(icnsOutputPath), { recursive: true });\n await fs.mkdir(path.dirname(icoOutputPath), { recursive: true });\n await fs.mkdir(path.dirname(cachePath), { recursive: true });\n await fs.writeFile(outputPath, rendered);\n await encodeNativeIcons(rendered, macosRendered, icnsOutputPath, icoOutputPath);\n await writeLinuxIcons(rendered, metadata.linuxPngOutputPaths);\n await writeManifest(metadata);\n await fs.writeFile(\n cachePath,\n `${JSON.stringify(metadata, null, 2)}\\n`,\n \"utf8\"\n );\n return metadata;\n}\n\n/** Create the Vite plugin used by both serve and build modes. */\nexport function openTrayAppIconPlugin(\n options: OpenTrayAppIconPluginOptions\n): Plugin {\n let generation: Promise<OpenTrayAppIconCacheMetadata> | undefined;\n\n return {\n name: \"opentray/app-icon\",\n enforce: \"pre\",\n async configResolved(config) {\n const outputPath =\n options.outputPath ??\n path.resolve(config.root, \"static/icons/app-icon.png\");\n const icnsOutputPath =\n options.icnsOutputPath ??\n path.resolve(config.root, \"static/icons/app-icon.icns\");\n const icoOutputPath =\n options.icoOutputPath ??\n path.resolve(config.root, \"static/icons/app-icon.ico\");\n const linuxOutputDirectory =\n options.linuxOutputDirectory ??\n path.resolve(config.root, \"static/icons/linux\");\n const manifestOutputPath =\n options.manifestOutputPath ??\n path.resolve(config.root, \"static/icons/app-icon.json\");\n const cachePath =\n options.cachePath ?? path.resolve(config.root, \".cache/app-icon.json\");\n generation ??= generateOpenTrayAppIcon({\n sourcePath: path.resolve(options.sourcePath),\n ...(options.composed === true ? { composed: true } : {}),\n ...(options.macosSourcePath === undefined\n ? {}\n : { macosSourcePath: path.resolve(options.macosSourcePath) }),\n outputPath,\n icnsOutputPath,\n icoOutputPath,\n linuxOutputDirectory,\n manifestOutputPath,\n cachePath,\n });\n await generation;\n },\n };\n}\n\nasync function createCacheMetadata(options: {\n sourcePath: string;\n implementationPath: string;\n implementationSourcePath?: string;\n /** Pass-through mode: skip glyph re-tiling (part of cache identity). */\n composed?: boolean;\n /** Separate macOS content source (part of cache identity). */\n macosSourcePath?: string;\n outputPath: string;\n icnsOutputPath: string;\n icoOutputPath: string;\n linuxOutputDirectory: string;\n manifestOutputPath: string;\n}): Promise<OpenTrayAppIconCacheMetadata> {\n const sourceImplementationPath =\n options.implementationSourcePath ??\n (await resolveSourceImplementationPath(options.implementationPath));\n const linuxPngOutputPaths = LINUX_SIZES.map((size) => ({\n size,\n path: path.resolve(\n options.linuxOutputDirectory,\n `${size}x${size}`,\n \"app-icon.png\"\n ),\n }));\n const icnsOutputPath = path.resolve(options.icnsOutputPath);\n const icoOutputPath = path.resolve(options.icoOutputPath);\n const appIcon: AppIcon = [\n {\n platform: \"darwin\",\n format: \"icns\",\n source: { type: \"file\", path: icnsOutputPath },\n },\n {\n platform: \"windows\",\n format: \"ico\",\n source: { type: \"file\", path: icoOutputPath },\n },\n ...linuxPngOutputPaths.map(({ size, path: pngPath }) => ({\n platform: \"linux\" as const,\n format: \"png\" as const,\n size,\n source: { type: \"file\" as const, path: pngPath },\n })),\n ];\n return {\n schemaVersion: CACHE_SCHEMA_VERSION,\n sourceSha256: await sha256(options.sourcePath),\n ...(options.macosSourcePath === undefined\n ? {}\n : { macosSourceSha256: await sha256(options.macosSourcePath) }),\n ...(options.composed === true ? { composed: true } : {}),\n sourceImplementationSha256:\n sourceImplementationPath === null\n ? null\n : await sha256(sourceImplementationPath),\n implementationSha256: await sha256(options.implementationPath),\n recipeVersion: RECIPE_VERSION,\n sharpVersion: await packageVersion(\"sharp\"),\n iconEncoderVersion: await packageVersion(\"@shockpkg/icon-encoder\"),\n figmaSquircleVersion: await packageVersion(\"figma-squircle\"),\n outputPath: path.resolve(options.outputPath),\n icnsOutputPath,\n icoOutputPath,\n linuxPngOutputPaths,\n manifestOutputPath: path.resolve(options.manifestOutputPath),\n appIcon,\n };\n}\n\nasync function renderAppIcon(sourcePath: string, composed = false): Promise<Buffer> {\n if (composed) {\n // Pre-composed art: normalize to the 1024 canvas and pass through —\n // the background and squircle mask are already baked in.\n return sharp(sourcePath, { failOn: \"none\" })\n .resize(ICON_SIZE, ICON_SIZE, { fit: \"contain\", kernel: sharp.kernel.lanczos3 })\n .withMetadata({ density: APP_ICON_DENSITY })\n .png({ compressionLevel: 9 })\n .toBuffer();\n }\n const symbol = await sharp(sourcePath)\n .trim({ threshold: 0 })\n .resize(SYMBOL_SIZE, SYMBOL_SIZE, {\n fit: \"inside\",\n kernel: sharp.kernel.lanczos3,\n })\n .png()\n .toBuffer({ resolveWithObject: true });\n const symbolLeft = Math.round((ICON_SIZE - symbol.info.width) / 2);\n const symbolTop = Math.round((ICON_SIZE - symbol.info.height) / 2);\n const squirclePath = getSvgPath({\n width: TILE_SIZE,\n height: TILE_SIZE,\n cornerRadius: TILE_RADIUS,\n cornerSmoothing: TILE_SMOOTHING,\n preserveSmoothing: true,\n });\n const whiteTile = Buffer.from(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${TILE_SIZE}\" height=\"${TILE_SIZE}\"><path d=\"${squirclePath}\" fill=\"#fff\"/></svg>`\n );\n return sharp({\n create: {\n width: ICON_SIZE,\n height: ICON_SIZE,\n channels: 4,\n background: { r: 0, g: 0, b: 0, alpha: 0 },\n },\n })\n .composite([\n { input: whiteTile, top: TILE_INSET, left: TILE_INSET },\n { input: symbol.data, top: symbolTop, left: symbolLeft },\n ])\n .withMetadata({ density: APP_ICON_DENSITY })\n .png({ compressionLevel: 9 })\n .toBuffer();\n}\n\nasync function encodeNativeIcons(\n rendered: Buffer,\n macosRendered: Buffer,\n icnsOutputPath: string,\n icoOutputPath: string\n): Promise<void> {\n const cacheFor = (source: Buffer): {\n pngAt(size: number): Promise<Buffer>;\n } => {\n const bySize = new Map<number, Buffer>();\n return {\n async pngAt(size: number): Promise<Buffer> {\n const cached = bySize.get(size);\n if (cached !== undefined) return cached;\n const png = await sharp(source)\n .resize(size, size, { fit: \"contain\" })\n .withMetadata({ density: APP_ICON_DENSITY })\n .png({ compressionLevel: 9 })\n .toBuffer();\n bySize.set(size, png);\n return png;\n },\n };\n };\n const windows = cacheFor(rendered);\n const macos = cacheFor(macosRendered);\n\n const icns = new IconIcns();\n icns.toc = true;\n for (const { tag, size } of ICNS_REPRESENTATIONS) {\n await icns.addFromPng(await macos.pngAt(size), [tag], false);\n }\n await fs.writeFile(icnsOutputPath, icns.encode());\n\n const ico = new IconIco();\n for (const size of ICO_SIZES) {\n await ico.addFromPng(await windows.pngAt(size), null, false);\n }\n await fs.writeFile(icoOutputPath, ico.encode());\n}\n\nasync function writeLinuxIcons(\n rendered: Buffer,\n outputs: OpenTrayAppIconCacheMetadata[\"linuxPngOutputPaths\"]\n): Promise<void> {\n await Promise.all(\n outputs.map(async ({ size, path: outputPath }) => {\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await sharp(rendered)\n .resize(size, size, { fit: \"contain\" })\n .withMetadata({ density: APP_ICON_DENSITY })\n .png({ compressionLevel: 9 })\n .toFile(outputPath);\n })\n );\n}\n\nasync function writeManifest(\n metadata: OpenTrayAppIconCacheMetadata\n): Promise<void> {\n const manifestDirectory = path.dirname(metadata.manifestOutputPath);\n const relativeSource = (\n sourcePath: string\n ): { type: \"file\"; path: string } => ({\n type: \"file\",\n path: path\n .relative(manifestDirectory, sourcePath)\n .split(path.sep)\n .join(\"/\"),\n });\n const manifest: OpenTrayAppIconManifest = {\n schemaVersion: 1,\n appIcon: [\n {\n platform: \"darwin\",\n format: \"icns\",\n source: relativeSource(metadata.icnsOutputPath),\n },\n {\n platform: \"windows\",\n format: \"ico\",\n source: relativeSource(metadata.icoOutputPath),\n },\n ...metadata.linuxPngOutputPaths.map(({ size, path: pngPath }) => ({\n platform: \"linux\" as const,\n format: \"png\" as const,\n size,\n source: relativeSource(pngPath),\n })),\n ],\n };\n await fs.mkdir(manifestDirectory, { recursive: true });\n await fs.writeFile(\n metadata.manifestOutputPath,\n `${JSON.stringify(manifest, null, 2)}\\n`\n );\n}\n\nasync function cacheMatches(\n file: string,\n expected: OpenTrayAppIconCacheMetadata\n): Promise<boolean> {\n try {\n const parsed: unknown = JSON.parse(await fs.readFile(file, \"utf8\"));\n if (!isCacheMetadata(parsed) || !sameCacheIdentity(parsed, expected))\n return false;\n await Promise.all([\n fs.access(expected.outputPath),\n fs.access(expected.icnsOutputPath),\n fs.access(expected.icoOutputPath),\n fs.access(expected.manifestOutputPath),\n ...expected.linuxPngOutputPaths.map(({ path: outputPath }) =>\n fs.access(outputPath)\n ),\n ]);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction sameCacheIdentity(\n actual: OpenTrayAppIconCacheMetadata,\n expected: OpenTrayAppIconCacheMetadata\n): boolean {\n return (\n actual.schemaVersion === expected.schemaVersion &&\n actual.sourceSha256 === expected.sourceSha256 &&\n actual.macosSourceSha256 === expected.macosSourceSha256 &&\n actual.composed === expected.composed &&\n actual.sourceImplementationSha256 === expected.sourceImplementationSha256 &&\n actual.implementationSha256 === expected.implementationSha256 &&\n actual.recipeVersion === expected.recipeVersion &&\n actual.sharpVersion === expected.sharpVersion &&\n actual.iconEncoderVersion === expected.iconEncoderVersion &&\n actual.figmaSquircleVersion === expected.figmaSquircleVersion &&\n actual.outputPath === expected.outputPath &&\n actual.icnsOutputPath === expected.icnsOutputPath &&\n actual.icoOutputPath === expected.icoOutputPath &&\n actual.manifestOutputPath === expected.manifestOutputPath &&\n JSON.stringify(actual.linuxPngOutputPaths) ===\n JSON.stringify(expected.linuxPngOutputPaths) &&\n JSON.stringify(actual.appIcon) === JSON.stringify(expected.appIcon)\n );\n}\n\nfunction isCacheMetadata(\n value: unknown\n): value is OpenTrayAppIconCacheMetadata {\n if (typeof value !== \"object\" || value === null) return false;\n const record = value as Record<string, unknown>;\n return (\n typeof record.schemaVersion === \"number\" &&\n typeof record.sourceSha256 === \"string\" &&\n (record.macosSourceSha256 === undefined ||\n typeof record.macosSourceSha256 === \"string\") &&\n (record.composed === undefined || typeof record.composed === \"boolean\") &&\n (record.sourceImplementationSha256 === null ||\n typeof record.sourceImplementationSha256 === \"string\") &&\n typeof record.implementationSha256 === \"string\" &&\n typeof record.recipeVersion === \"string\" &&\n typeof record.sharpVersion === \"string\" &&\n typeof record.iconEncoderVersion === \"string\" &&\n typeof record.figmaSquircleVersion === \"string\" &&\n typeof record.outputPath === \"string\" &&\n typeof record.icnsOutputPath === \"string\" &&\n typeof record.icoOutputPath === \"string\" &&\n Array.isArray(record.linuxPngOutputPaths) &&\n typeof record.manifestOutputPath === \"string\" &&\n Array.isArray(record.appIcon)\n );\n}\n\nasync function resolveSourceImplementationPath(\n implementationPath: string\n): Promise<string | null> {\n if (implementationPath.endsWith(`${path.sep}src${path.sep}app-icon.ts`)) {\n return implementationPath;\n }\n const candidate = path.join(\n path.dirname(path.dirname(implementationPath)),\n \"src\",\n \"app-icon.ts\"\n );\n try {\n await fs.access(candidate);\n return candidate;\n } catch {\n return null;\n }\n}\n\nasync function packageVersion(packageName: string): Promise<string> {\n const entryPath = require.resolve(packageName);\n let directory = path.dirname(entryPath);\n while (true) {\n const packagePath = path.join(directory, \"package.json\");\n try {\n const parsed: unknown = JSON.parse(\n await fs.readFile(packagePath, \"utf8\")\n );\n if (isPackageMetadata(parsed, packageName)) return parsed.version;\n } catch {\n // Continue towards the package root; package exports may hide package.json.\n }\n const parent = path.dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n throw new Error(`Unable to resolve ${packageName} package version`);\n}\n\nfunction isPackageMetadata(\n value: unknown,\n packageName: string\n): value is { name: string; version: string } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"name\" in value &&\n value.name === packageName &&\n \"version\" in value &&\n typeof value.version === \"string\"\n );\n}\n\nasync function sha256(file: string): Promise<string> {\n return crypto\n .createHash(\"sha256\")\n .update(await fs.readFile(file))\n .digest(\"hex\");\n}\n","// Orthogonal intents (maintained 2026-07-20; original user request: expose the\n// OpenTray Vite packaging adapter and move skill-creator-v2 app-icon generation into it):\n// 1. Stage Vite bundle metadata and native runtime artifacts through one adapter.\n// 2. Re-export the app-icon generator without coupling the packaging contract to a consumer.\n// Compromise: both exports share the package entrypoint because Vite resolves one public adapter\n// module and the icon plugin has no runtime dependency on the artifact manifest.\n\nimport { resolve } from \"node:path\";\n\nimport {\n buildDarwinAppBundle,\n stageOpenTrayPackage,\n type DarwinAppBundleOptions,\n type OpenTrayArtifactInput,\n type OpenTrayPackagingApp,\n type OpenTrayPackageManifest,\n type OpenTrayPackageResult,\n type OpenTrayDarwinAppBundleResult,\n} from \"@opentray/packaging\";\n\nexport interface OpenTrayVitePluginOptions {\n readonly app: OpenTrayPackagingApp;\n readonly runtimeHost: OpenTrayArtifactInput;\n readonly nativeArtifacts?: Readonly<Record<string, OpenTrayArtifactInput>>;\n readonly companionAssets?: Readonly<Record<string, OpenTrayArtifactInput>>;\n readonly entry?: string;\n readonly manifestPath?: string;\n}\n\nexport interface ViteResolvedConfigLike {\n readonly root: string;\n readonly mode: string;\n readonly build: {\n readonly outDir: string;\n };\n}\n\nexport interface ViteOutputChunkLike {\n readonly type?: string;\n readonly isEntry?: boolean;\n readonly fileName?: string;\n readonly facadeModuleId?: string | null;\n readonly name?: string;\n}\n\nexport type ViteBundleLike = Readonly<Record<string, unknown>>;\n\nexport interface OpenTrayVitePlugin {\n readonly name: \"opentray-packaging\";\n readonly apply: \"build\";\n configResolved(config: ViteResolvedConfigLike): void;\n writeBundle(options: unknown, bundle: ViteBundleLike): Promise<void>;\n readonly getLastResult: () => OpenTrayPackageResult | undefined;\n}\n\nexport interface OpenTrayViteAppBundlePluginOptions\n extends Omit<DarwinAppBundleOptions, \"bundlePath\" | \"reinitialize\"> {\n /** Optional output path. Defaults to `<vite outDir>/<appName>.app`. */\n readonly bundlePath?: string;\n}\n\nexport interface OpenTrayViteAppBundlePlugin {\n readonly name: \"opentray-app-bundle\";\n readonly apply: \"build\";\n configResolved(config: ViteResolvedConfigLike): void;\n writeBundle(): Promise<void>;\n readonly getLastResult: () => OpenTrayDarwinAppBundleResult | undefined;\n}\n\n/** Vite lifecycle adapter for the shared Darwin app bundle contract. */\nexport const openTrayAppBundlePlugin = (\n options: OpenTrayViteAppBundlePluginOptions,\n): OpenTrayViteAppBundlePlugin => {\n let config: ViteResolvedConfigLike | undefined;\n let lastResult: OpenTrayDarwinAppBundleResult | undefined;\n return {\n name: \"opentray-app-bundle\",\n apply: \"build\",\n configResolved(resolvedConfig) {\n config = resolvedConfig;\n },\n async writeBundle() {\n const resolvedConfig = config ?? {\n root: process.cwd(),\n mode: \"production\",\n build: { outDir: \"dist\" },\n };\n const bundlePath =\n options.bundlePath ?? resolve(\n resolvedConfig.root,\n resolvedConfig.build.outDir,\n `${options.appName}.app`,\n );\n lastResult = await buildDarwinAppBundle({ ...options, bundlePath });\n },\n getLastResult: () => lastResult,\n };\n};\n\nexport const openTrayVitePlugin = (options: OpenTrayVitePluginOptions): OpenTrayVitePlugin => {\n let config: ViteResolvedConfigLike | undefined;\n let lastResult: OpenTrayPackageResult | undefined;\n\n return {\n name: \"opentray-packaging\",\n apply: \"build\",\n configResolved(resolvedConfig) {\n config = resolvedConfig;\n },\n async writeBundle(_options, bundle) {\n const resolvedConfig = config ?? {\n root: process.cwd(),\n mode: \"production\",\n build: { outDir: \"dist\" },\n };\n lastResult = await stageOpenTrayPackage({\n app: options.app,\n outDir: resolve(resolvedConfig.root, resolvedConfig.build.outDir),\n entry: options.entry ?? resolveViteEntry(bundle),\n adapter: { name: \"vite\", mode: resolvedConfig.mode },\n runtimeHost: options.runtimeHost,\n ...(options.nativeArtifacts === undefined\n ? {}\n : { nativeArtifacts: options.nativeArtifacts }),\n ...(options.companionAssets === undefined\n ? {}\n : { companionAssets: options.companionAssets }),\n ...(options.manifestPath === undefined ? {} : { manifestPath: options.manifestPath }),\n });\n },\n getLastResult: () => lastResult,\n };\n};\n\nexport const resolveViteEntry = (bundle: ViteBundleLike): string => {\n const entry = Object.values(bundle)\n .map(asOutputChunk)\n .find((chunk): chunk is ViteOutputChunkLike => chunk?.isEntry === true);\n const identity = entry?.facadeModuleId ?? entry?.fileName ?? entry?.name;\n if (identity === undefined || identity.length === 0) {\n throw new Error(\"OpenTray Vite packaging requires a Vite entry chunk or explicit entry option\");\n }\n return identity;\n};\n\nconst asOutputChunk = (value: unknown): ViteOutputChunkLike | undefined => {\n if (typeof value !== \"object\" || value === null) {\n return undefined;\n }\n const record = value as Record<string, unknown>;\n return {\n ...(record.type === \"chunk\" ? { type: \"chunk\" } : {}),\n ...(typeof record.isEntry === \"boolean\" ? { isEntry: record.isEntry } : {}),\n ...(typeof record.fileName === \"string\" ? { fileName: record.fileName } : {}),\n ...(typeof record.facadeModuleId === \"string\" || record.facadeModuleId === null\n ? { facadeModuleId: record.facadeModuleId }\n : {}),\n ...(typeof record.name === \"string\" ? { name: record.name } : {}),\n };\n};\n\nexport type { OpenTrayPackageManifest, OpenTrayPackageResult };\n\nexport {\n generateOpenTrayAppIcon,\n openTrayAppIconPlugin,\n type OpenTrayAppIconCacheMetadata,\n type OpenTrayAppIconManifest,\n type OpenTrayAppIconOptions,\n type OpenTrayAppIconPluginOptions,\n} from \"./app-icon\";\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentray/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.1",
|
|
4
4
|
"description": "Vite adapter for the OpenTray runtime artifact packaging contract.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"app-icon",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"@shockpkg/icon-encoder": "^3.2.3",
|
|
31
31
|
"figma-squircle": "^1.1.0",
|
|
32
32
|
"sharp": "^0.33.5",
|
|
33
|
-
"@opentray/
|
|
34
|
-
"@opentray/
|
|
33
|
+
"@opentray/spec": "0.19.1",
|
|
34
|
+
"@opentray/packaging": "0.19.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"tsdown": "^0.22.1",
|