@openfairygui/cli 0.2.0-alpha.11 → 0.2.0-alpha.13
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.mjs +144 -111
- package/package.json +4 -4
- package/src/commands/publish.ts +16 -57
package/dist/cli.mjs
CHANGED
|
@@ -3,7 +3,6 @@ import { Command } from "commander";
|
|
|
3
3
|
import { createNodeBackendRuntime } from "@openfairygui/backend/node";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import { createJiti } from "jiti";
|
|
7
6
|
import * as fs$1 from "node:fs/promises";
|
|
8
7
|
import fs from "node:fs/promises";
|
|
9
8
|
//#region src/commands/backend-capabilities.ts
|
|
@@ -21884,7 +21883,7 @@ async function resolveEditorCompatibleResourceOrder(pkg, allResources, options)
|
|
|
21884
21883
|
*
|
|
21885
21884
|
* This transform performs MaxRects bin-packing on all ImageResource items
|
|
21886
21885
|
* within each package, creating Atlas and Sprite property nodes. When an
|
|
21887
|
-
*
|
|
21886
|
+
* a raster backend is provided, it also composites the actual PNG files.
|
|
21888
21887
|
*
|
|
21889
21888
|
* When `trimImage` is enabled and encoder is available, transparent pixels
|
|
21890
21889
|
* at image edges are trimmed before packing. The trimmed offset and original
|
|
@@ -22486,7 +22485,7 @@ function groupStandaloneInputs(doc, inputs, options) {
|
|
|
22486
22485
|
};
|
|
22487
22486
|
}
|
|
22488
22487
|
/**
|
|
22489
|
-
* Trim transparent edges from an image using
|
|
22488
|
+
* Trim transparent edges from an image using the host raster backend.
|
|
22490
22489
|
* Returns the trimmed buffer, dimensions, and offsets.
|
|
22491
22490
|
* Falls back to the original image if trim fails (e.g. no alpha channel, no transparent edges).
|
|
22492
22491
|
*/
|
|
@@ -22576,7 +22575,11 @@ async function _collectImage(resource, pkg, inputs, encoder, options, doTrim, lo
|
|
|
22576
22575
|
}
|
|
22577
22576
|
sourceHasAlpha = metadata.hasAlpha === true || metadata.channels === 4;
|
|
22578
22577
|
if (/\.svg$/i.test(resolveImageFileName$1(resource)) && declaredWidth > 0 && declaredHeight > 0) {
|
|
22579
|
-
rasterizedBuffer = await encoder(filePath).resize(
|
|
22578
|
+
rasterizedBuffer = await encoder(filePath).resize({
|
|
22579
|
+
width: declaredWidth,
|
|
22580
|
+
height: declaredHeight,
|
|
22581
|
+
fit: "fill"
|
|
22582
|
+
}).png().toBuffer();
|
|
22580
22583
|
sourceHasAlpha = true;
|
|
22581
22584
|
}
|
|
22582
22585
|
} catch {
|
|
@@ -23045,61 +23048,10 @@ const FGUI_TYPESCRIPT_BINDER_TEMPLATE = `{{generatedMark}}
|
|
|
23045
23048
|
}
|
|
23046
23049
|
`;
|
|
23047
23050
|
//#endregion
|
|
23048
|
-
//#region ../functions/src/plugins/
|
|
23049
|
-
const importNative = new Function("id", "return import(id)");
|
|
23050
|
-
async function loadPlugins(doc, pluginsDir) {
|
|
23051
|
-
if (!pluginsDir) return [];
|
|
23052
|
-
const fs = await importNative("node:fs/promises");
|
|
23053
|
-
const path = await importNative("node:path");
|
|
23054
|
-
let entries;
|
|
23055
|
-
try {
|
|
23056
|
-
entries = await fs.readdir(pluginsDir, { withFileTypes: true });
|
|
23057
|
-
} catch {
|
|
23058
|
-
return [];
|
|
23059
|
-
}
|
|
23060
|
-
const plugins = [];
|
|
23061
|
-
for (const entry of entries) {
|
|
23062
|
-
if (!entry.isDirectory()) continue;
|
|
23063
|
-
const pluginDir = path.join(pluginsDir, entry.name);
|
|
23064
|
-
try {
|
|
23065
|
-
const manifest = await readPluginManifest(fs, path, pluginDir);
|
|
23066
|
-
if (!manifest) continue;
|
|
23067
|
-
const plugin = await loadPlugin(resolvePluginMain(path, pluginDir, manifest));
|
|
23068
|
-
plugins.push({
|
|
23069
|
-
name: manifest.name,
|
|
23070
|
-
plugin
|
|
23071
|
-
});
|
|
23072
|
-
} catch (error) {
|
|
23073
|
-
doc.getLogger().warn(`publish: Plugin "${entry.name}" was skipped: ${formatPluginError(error)}`);
|
|
23074
|
-
}
|
|
23075
|
-
}
|
|
23076
|
-
return plugins;
|
|
23077
|
-
}
|
|
23051
|
+
//#region ../functions/src/plugins/types.ts
|
|
23078
23052
|
function formatPluginError(error) {
|
|
23079
23053
|
return error instanceof Error ? error.message : String(error);
|
|
23080
23054
|
}
|
|
23081
|
-
async function readPluginManifest(fs, path, pluginDir) {
|
|
23082
|
-
const manifestPath = path.join(pluginDir, "package.json");
|
|
23083
|
-
const content = await fs.readFile(manifestPath, "utf-8");
|
|
23084
|
-
const manifest = JSON.parse(content);
|
|
23085
|
-
if (!manifest.name) throw new Error(`Codegen plugin at ${pluginDir} is missing package.json name.`);
|
|
23086
|
-
if (!manifest.main) throw new Error(`Codegen plugin "${manifest.name}" is missing package.json main.`);
|
|
23087
|
-
return manifest;
|
|
23088
|
-
}
|
|
23089
|
-
function resolvePluginMain(path, pluginDir, manifest) {
|
|
23090
|
-
const mainPath = path.resolve(pluginDir, manifest.main);
|
|
23091
|
-
const relative = path.relative(pluginDir, mainPath);
|
|
23092
|
-
if (relative.startsWith("..") || path.isAbsolute(relative)) throw new Error(`Codegen plugin "${manifest.name}" main must resolve inside its plugin directory.`);
|
|
23093
|
-
return mainPath;
|
|
23094
|
-
}
|
|
23095
|
-
async function loadPlugin(mainPath) {
|
|
23096
|
-
const mod = await createJiti(import.meta.url).import(mainPath);
|
|
23097
|
-
const defaultExport = mod.default;
|
|
23098
|
-
return isObject(defaultExport) ? defaultExport : mod;
|
|
23099
|
-
}
|
|
23100
|
-
function isObject(value) {
|
|
23101
|
-
return value !== null && typeof value === "object";
|
|
23102
|
-
}
|
|
23103
23055
|
//#endregion
|
|
23104
23056
|
//#region ../functions/src/codegen.ts
|
|
23105
23057
|
const AUTO_GENERATED_CODE_MARK = "/** This is an automatically generated class by FairyGUI. Please do not modify it. **/";
|
|
@@ -24331,14 +24283,6 @@ async function runPublishPluginHook(plugins, hook, doc, options) {
|
|
|
24331
24283
|
}
|
|
24332
24284
|
}
|
|
24333
24285
|
}
|
|
24334
|
-
function resolvePublishPluginsDir(doc, options) {
|
|
24335
|
-
const fs = options.fs;
|
|
24336
|
-
const projectDir = doc.getProjectDir?.() ?? "";
|
|
24337
|
-
if (projectDir) return fs?.join ? fs.join(projectDir, "plugins") : `${projectDir.replace(/[/\\]+$/, "")}/plugins`;
|
|
24338
|
-
const projectBasePath = resolveProjectBasePath(options.basePath);
|
|
24339
|
-
if (!projectBasePath) return "";
|
|
24340
|
-
return fs?.join ? fs.join(projectBasePath, "plugins") : `${projectBasePath.replace(/[/\\]+$/, "")}/plugins`;
|
|
24341
|
-
}
|
|
24342
24286
|
const UNITY_PROJECT_TYPE = ProjectType.Unity;
|
|
24343
24287
|
const COCOS_CREATOR_PROJECT_TYPE = ProjectType.CocosCreator;
|
|
24344
24288
|
function resolveDefaultPublishFileExtension(projectType, publishSettings) {
|
|
@@ -24942,10 +24886,13 @@ async function exportPackageExternalResources(pkg, outputDir, basePath, fs, read
|
|
|
24942
24886
|
* Publishes a FairyGUI project.
|
|
24943
24887
|
*
|
|
24944
24888
|
* Orchestrates:
|
|
24945
|
-
* 1. Atlas packing (MaxRects layout + optional
|
|
24889
|
+
* 1. Atlas packing (MaxRects layout + optional raster compositing)
|
|
24946
24890
|
* 2. Per-package .fui binary serialization
|
|
24947
24891
|
* 3. File writing to the output directory
|
|
24948
24892
|
*
|
|
24893
|
+
* This is the capability-injected core. Standard hosts should use
|
|
24894
|
+
* `publishNode()` or `publishBrowser()` through their dedicated entries.
|
|
24895
|
+
*
|
|
24949
24896
|
* ```ts
|
|
24950
24897
|
* import sharp from 'sharp';
|
|
24951
24898
|
* const io = new NodeIO();
|
|
@@ -25055,8 +25002,7 @@ function publish(options) {
|
|
|
25055
25002
|
const root = doc.getRoot();
|
|
25056
25003
|
const logger = doc.getLogger();
|
|
25057
25004
|
const projectBasePath = resolveProjectBasePath(options.basePath) || doc.getProjectDir?.() || "";
|
|
25058
|
-
const
|
|
25059
|
-
const plugins = pluginsDir ? await loadPlugins(doc, pluginsDir) : [];
|
|
25005
|
+
const plugins = options.plugins ?? [];
|
|
25060
25006
|
await runPublishPluginHook(plugins, "onPublishStart", doc, options);
|
|
25061
25007
|
const resolved = resolveProjectPublishConfig();
|
|
25062
25008
|
let allPackages = root.listPackages();
|
|
@@ -25093,7 +25039,7 @@ function publish(options) {
|
|
|
25093
25039
|
if (unresolvedPlan) throw new Error(`publish: no output directory resolved for package "${unresolvedPlan.pkg.getName()}". Provide --output, or configure global publish.path / package publishPath.`);
|
|
25094
25040
|
const writerFs = toBinaryWriterFileSystem(options.fs);
|
|
25095
25041
|
for (const plan of plans) await publishPackage(plan, writerFs, allDocPackages.indexOf(plan.pkg));
|
|
25096
|
-
await publishCodeGeneration(doc, {
|
|
25042
|
+
if (options.codeGeneration !== false) await publishCodeGeneration(doc, {
|
|
25097
25043
|
basePath: options.basePath,
|
|
25098
25044
|
fs: options.fs,
|
|
25099
25045
|
packages: allPackages,
|
|
@@ -25323,6 +25269,131 @@ function printReport(report) {
|
|
|
25323
25269
|
}
|
|
25324
25270
|
}
|
|
25325
25271
|
//#endregion
|
|
25272
|
+
//#region ../functions/src/adapters/node/plugins.ts
|
|
25273
|
+
const importNative$1 = new Function("id", "return import(id)");
|
|
25274
|
+
async function loadPlugins(doc, pluginsDir) {
|
|
25275
|
+
if (!pluginsDir) return [];
|
|
25276
|
+
const fs = await importNative$1("node:fs/promises");
|
|
25277
|
+
const path = await importNative$1("node:path");
|
|
25278
|
+
let entries;
|
|
25279
|
+
try {
|
|
25280
|
+
entries = await fs.readdir(pluginsDir, { withFileTypes: true });
|
|
25281
|
+
} catch {
|
|
25282
|
+
return [];
|
|
25283
|
+
}
|
|
25284
|
+
const plugins = [];
|
|
25285
|
+
for (const entry of entries) {
|
|
25286
|
+
if (!entry.isDirectory()) continue;
|
|
25287
|
+
const pluginDir = path.join(pluginsDir, entry.name);
|
|
25288
|
+
try {
|
|
25289
|
+
const manifest = await readPluginManifest(fs, path, pluginDir);
|
|
25290
|
+
if (!manifest) continue;
|
|
25291
|
+
const plugin = await loadPlugin(resolvePluginMain(path, pluginDir, manifest));
|
|
25292
|
+
plugins.push({
|
|
25293
|
+
name: manifest.name,
|
|
25294
|
+
plugin
|
|
25295
|
+
});
|
|
25296
|
+
} catch (error) {
|
|
25297
|
+
doc.getLogger().warn(`publish: Plugin "${entry.name}" was skipped: ${formatPluginError(error)}`);
|
|
25298
|
+
}
|
|
25299
|
+
}
|
|
25300
|
+
return plugins;
|
|
25301
|
+
}
|
|
25302
|
+
async function readPluginManifest(fs, path, pluginDir) {
|
|
25303
|
+
const manifestPath = path.join(pluginDir, "package.json");
|
|
25304
|
+
const content = await fs.readFile(manifestPath, "utf-8");
|
|
25305
|
+
const manifest = JSON.parse(content);
|
|
25306
|
+
if (!manifest.name) throw new Error(`Codegen plugin at ${pluginDir} is missing package.json name.`);
|
|
25307
|
+
if (!manifest.main) throw new Error(`Codegen plugin "${manifest.name}" is missing package.json main.`);
|
|
25308
|
+
return manifest;
|
|
25309
|
+
}
|
|
25310
|
+
function resolvePluginMain(path, pluginDir, manifest) {
|
|
25311
|
+
const mainPath = path.resolve(pluginDir, manifest.main);
|
|
25312
|
+
const relative = path.relative(pluginDir, mainPath);
|
|
25313
|
+
if (relative.startsWith("..") || path.isAbsolute(relative)) throw new Error(`Codegen plugin "${manifest.name}" main must resolve inside its plugin directory.`);
|
|
25314
|
+
return mainPath;
|
|
25315
|
+
}
|
|
25316
|
+
async function loadPlugin(mainPath) {
|
|
25317
|
+
const { createJiti } = await importNative$1("jiti");
|
|
25318
|
+
const mod = await createJiti(import.meta.url).import(mainPath);
|
|
25319
|
+
const defaultExport = mod.default;
|
|
25320
|
+
return isObject(defaultExport) ? defaultExport : mod;
|
|
25321
|
+
}
|
|
25322
|
+
function isObject(value) {
|
|
25323
|
+
return value !== null && typeof value === "object";
|
|
25324
|
+
}
|
|
25325
|
+
//#endregion
|
|
25326
|
+
//#region ../functions/src/adapters/node/publish.ts
|
|
25327
|
+
const importNative = new Function("id", "return import(id)");
|
|
25328
|
+
async function createNodePublishFileSystem() {
|
|
25329
|
+
const [fs, path] = await Promise.all([importNative("node:fs/promises"), importNative("node:path")]);
|
|
25330
|
+
return {
|
|
25331
|
+
async readFileRaw(filePath) {
|
|
25332
|
+
const data = await fs.readFile(filePath);
|
|
25333
|
+
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
25334
|
+
},
|
|
25335
|
+
async writeFileRaw(filePath, data) {
|
|
25336
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
25337
|
+
await fs.writeFile(filePath, data);
|
|
25338
|
+
},
|
|
25339
|
+
async mkdir(dirPath) {
|
|
25340
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
25341
|
+
},
|
|
25342
|
+
async readdir(dirPath) {
|
|
25343
|
+
return fs.readdir(dirPath);
|
|
25344
|
+
},
|
|
25345
|
+
async deleteFile(filePath) {
|
|
25346
|
+
await fs.rm(filePath, { force: true });
|
|
25347
|
+
},
|
|
25348
|
+
join(...paths) {
|
|
25349
|
+
return path.join(...paths);
|
|
25350
|
+
}
|
|
25351
|
+
};
|
|
25352
|
+
}
|
|
25353
|
+
async function resolveNodeAssetsPath(document, assetsPath) {
|
|
25354
|
+
if (assetsPath) return assetsPath;
|
|
25355
|
+
const projectDir = document.getProjectDir?.() ?? "";
|
|
25356
|
+
if (!projectDir) return void 0;
|
|
25357
|
+
return (await importNative("node:path")).join(projectDir, "assets");
|
|
25358
|
+
}
|
|
25359
|
+
async function loadSharpBackend() {
|
|
25360
|
+
try {
|
|
25361
|
+
const sharp = await importNative("sharp");
|
|
25362
|
+
return sharp.default ?? sharp;
|
|
25363
|
+
} catch {
|
|
25364
|
+
return;
|
|
25365
|
+
}
|
|
25366
|
+
}
|
|
25367
|
+
async function loadNodePublishPlugins(document, assetsPath) {
|
|
25368
|
+
const projectDir = document.getProjectDir?.() || (assetsPath ? resolveProjectBasePath(assetsPath) : "");
|
|
25369
|
+
if (!projectDir) return [];
|
|
25370
|
+
return loadPlugins(document, (await importNative("node:path")).join(projectDir, "plugins"));
|
|
25371
|
+
}
|
|
25372
|
+
/**
|
|
25373
|
+
* Publish a FairyGUI project through the standard Node host adapter.
|
|
25374
|
+
*
|
|
25375
|
+
* The adapter owns Node filesystem, Sharp, and project plugin discovery.
|
|
25376
|
+
* For custom environments, use the lower-level `publish()` core with explicit
|
|
25377
|
+
* capabilities instead.
|
|
25378
|
+
*/
|
|
25379
|
+
async function publishNode(options) {
|
|
25380
|
+
const { document, assetsPath: configuredAssetsPath, atlas, encoder: configuredEncoder, plugins: configuredPlugins, ...publishOptions } = options;
|
|
25381
|
+
const [fileSystem, assetsPath] = await Promise.all([createNodePublishFileSystem(), resolveNodeAssetsPath(document, configuredAssetsPath)]);
|
|
25382
|
+
const [encoder, plugins] = await Promise.all([configuredEncoder === void 0 ? loadSharpBackend() : Promise.resolve(configuredEncoder), configuredPlugins === void 0 ? loadNodePublishPlugins(document, assetsPath) : Promise.resolve(configuredPlugins)]);
|
|
25383
|
+
if (!encoder) document.getLogger().warn("publish: Sharp is unavailable; atlas layout will be generated without PNG output.");
|
|
25384
|
+
await document.transform(publish({
|
|
25385
|
+
...publishOptions,
|
|
25386
|
+
basePath: assetsPath,
|
|
25387
|
+
encoder,
|
|
25388
|
+
atlas: {
|
|
25389
|
+
...atlas,
|
|
25390
|
+
readFileRaw: fileSystem.readFileRaw
|
|
25391
|
+
},
|
|
25392
|
+
fs: fileSystem,
|
|
25393
|
+
plugins
|
|
25394
|
+
}));
|
|
25395
|
+
}
|
|
25396
|
+
//#endregion
|
|
25326
25397
|
//#region src/utils/project-type.ts
|
|
25327
25398
|
function parseProjectType(value) {
|
|
25328
25399
|
if (!value) return void 0;
|
|
@@ -25369,54 +25440,16 @@ function registerPublishCommand(program) {
|
|
|
25369
25440
|
});
|
|
25370
25441
|
console.log(`Settings: ext=${resolved.fileExtension}, compressed=${resolved.compressed}`);
|
|
25371
25442
|
if (options.branch) console.log(`Active branch: ${options.branch}`);
|
|
25372
|
-
|
|
25373
|
-
|
|
25374
|
-
readFileRaw: async (filePath) => {
|
|
25375
|
-
const buf = await fs.readFile(filePath);
|
|
25376
|
-
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
25377
|
-
}
|
|
25378
|
-
};
|
|
25379
|
-
let encoder;
|
|
25380
|
-
try {
|
|
25381
|
-
const sharp = await import("sharp");
|
|
25382
|
-
encoder = sharp.default ?? sharp;
|
|
25383
|
-
console.log("Sharp loaded — atlas PNGs will be generated.");
|
|
25384
|
-
} catch {
|
|
25385
|
-
console.log("Sharp not available — atlas PNGs will NOT be generated (layout only).");
|
|
25386
|
-
console.log(" Install sharp to enable: pnpm add sharp");
|
|
25387
|
-
}
|
|
25388
|
-
await doc.transform(publish({
|
|
25443
|
+
await publishNode({
|
|
25444
|
+
document: doc,
|
|
25389
25445
|
output: outputDir,
|
|
25390
25446
|
compressed: resolved.compressed,
|
|
25391
25447
|
fileExtension: resolved.fileExtension,
|
|
25392
25448
|
packages: resolved.packages,
|
|
25393
|
-
|
|
25394
|
-
|
|
25395
|
-
const buf = await fs.readFile(filePath);
|
|
25396
|
-
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
25397
|
-
},
|
|
25398
|
-
async writeFileRaw(filePath, data) {
|
|
25399
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
25400
|
-
await fs.writeFile(filePath, data);
|
|
25401
|
-
},
|
|
25402
|
-
async mkdir(dirPath) {
|
|
25403
|
-
await fs.mkdir(dirPath, { recursive: true });
|
|
25404
|
-
},
|
|
25405
|
-
async readdir(dirPath) {
|
|
25406
|
-
return fs.readdir(dirPath);
|
|
25407
|
-
},
|
|
25408
|
-
async deleteFile(filePath) {
|
|
25409
|
-
await fs.rm(filePath, { force: true });
|
|
25410
|
-
},
|
|
25411
|
-
join(...paths) {
|
|
25412
|
-
return path.join(...paths);
|
|
25413
|
-
}
|
|
25414
|
-
},
|
|
25415
|
-
encoder,
|
|
25416
|
-
basePath: path.join(projectRootDir, "assets"),
|
|
25417
|
-
atlas: atlasConfig,
|
|
25449
|
+
assetsPath: path.join(projectRootDir, "assets"),
|
|
25450
|
+
atlas: resolved.atlas,
|
|
25418
25451
|
branch: options.branch
|
|
25419
|
-
})
|
|
25452
|
+
});
|
|
25420
25453
|
console.log(`\nDone!${outputDir ? ` Output override: ${outputDir}` : ""}`);
|
|
25421
25454
|
});
|
|
25422
25455
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfairygui/cli",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.13",
|
|
4
4
|
"description": "FairyGUI Headless Authoring SDK — command-line interface.",
|
|
5
5
|
"author": "OpenFairyGUI Contributors",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,13 +33,13 @@
|
|
|
33
33
|
"restore"
|
|
34
34
|
],
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@openfairygui/core": "0.2.0-alpha.
|
|
37
|
-
"@openfairygui/functions": "0.2.0-alpha.
|
|
36
|
+
"@openfairygui/core": "0.2.0-alpha.13",
|
|
37
|
+
"@openfairygui/functions": "0.2.0-alpha.13"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"commander": "^14.0.2",
|
|
41
41
|
"jiti": "^2.7.0",
|
|
42
|
-
"@openfairygui/backend": "0.2.0-alpha.
|
|
42
|
+
"@openfairygui/backend": "0.2.0-alpha.13"
|
|
43
43
|
},
|
|
44
44
|
"optionalDependencies": {
|
|
45
45
|
"sharp": ">=0.33.0"
|
package/src/commands/publish.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
2
|
import { NodeIO } from '@openfairygui/core/node';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { resolvePublishOptions } from '@openfairygui/functions';
|
|
4
|
+
import { publishNode } from '@openfairygui/functions/node';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { resolveFairyPath } from '../utils/project-input.js';
|
|
7
7
|
import { parseProjectType } from '../utils/project-type.js';
|
|
@@ -23,7 +23,10 @@ export function registerPublishCommand(program: Command): void {
|
|
|
23
23
|
.option('-c, --compressed', 'Compress binary data (overrides project setting)')
|
|
24
24
|
.option('-p, --packages <a,b,c>', 'Only publish specific packages (comma-separated)')
|
|
25
25
|
.option('-b, --branch <name>', 'Active branch used by "主干合并活跃分支"; omit for main branch')
|
|
26
|
-
.option(
|
|
26
|
+
.option(
|
|
27
|
+
'-t, --project-type <name|id>',
|
|
28
|
+
'Override project type (for example: unity, layabox, cocoscreator, 0, 4, 3)',
|
|
29
|
+
)
|
|
27
30
|
.action(async (projectDir: string, options: PublishCommandOptions) => {
|
|
28
31
|
const fairyPath = await resolveFairyPath(projectDir);
|
|
29
32
|
const projectRootDir = path.dirname(fairyPath);
|
|
@@ -48,60 +51,16 @@ export function registerPublishCommand(program: Command): void {
|
|
|
48
51
|
console.log(`Active branch: ${options.branch}`);
|
|
49
52
|
}
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const sharp = await import('sharp');
|
|
62
|
-
encoder = sharp.default ?? sharp;
|
|
63
|
-
console.log('Sharp loaded — atlas PNGs will be generated.');
|
|
64
|
-
} catch {
|
|
65
|
-
console.log('Sharp not available — atlas PNGs will NOT be generated (layout only).');
|
|
66
|
-
console.log(' Install sharp to enable: pnpm add sharp');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const publishFs: NonNullable<PublishOptions['fs']> = {
|
|
70
|
-
async readFileRaw(filePath: string): Promise<Uint8Array> {
|
|
71
|
-
const buf = await fs.readFile(filePath);
|
|
72
|
-
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
73
|
-
},
|
|
74
|
-
async writeFileRaw(filePath: string, data: Uint8Array): Promise<void> {
|
|
75
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
76
|
-
await fs.writeFile(filePath, data);
|
|
77
|
-
},
|
|
78
|
-
async mkdir(dirPath: string): Promise<void> {
|
|
79
|
-
await fs.mkdir(dirPath, { recursive: true });
|
|
80
|
-
},
|
|
81
|
-
async readdir(dirPath: string): Promise<string[]> {
|
|
82
|
-
return fs.readdir(dirPath);
|
|
83
|
-
},
|
|
84
|
-
async deleteFile(filePath: string): Promise<void> {
|
|
85
|
-
await fs.rm(filePath, { force: true });
|
|
86
|
-
},
|
|
87
|
-
join(...paths: string[]): string {
|
|
88
|
-
return path.join(...paths);
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
await doc.transform(
|
|
93
|
-
publish({
|
|
94
|
-
output: outputDir,
|
|
95
|
-
compressed: resolved.compressed,
|
|
96
|
-
fileExtension: resolved.fileExtension,
|
|
97
|
-
packages: resolved.packages,
|
|
98
|
-
fs: publishFs,
|
|
99
|
-
encoder,
|
|
100
|
-
basePath: path.join(projectRootDir, 'assets'),
|
|
101
|
-
atlas: atlasConfig,
|
|
102
|
-
branch: options.branch,
|
|
103
|
-
}),
|
|
104
|
-
);
|
|
54
|
+
await publishNode({
|
|
55
|
+
document: doc,
|
|
56
|
+
output: outputDir,
|
|
57
|
+
compressed: resolved.compressed,
|
|
58
|
+
fileExtension: resolved.fileExtension,
|
|
59
|
+
packages: resolved.packages,
|
|
60
|
+
assetsPath: path.join(projectRootDir, 'assets'),
|
|
61
|
+
atlas: resolved.atlas,
|
|
62
|
+
branch: options.branch,
|
|
63
|
+
});
|
|
105
64
|
|
|
106
65
|
console.log(`\nDone!${outputDir ? ` Output override: ${outputDir}` : ''}`);
|
|
107
66
|
});
|