@openfairygui/functions 0.2.0 → 0.3.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/dist/index.cjs +3 -123
- package/dist/index.d.cts +11 -50
- package/dist/index.d.ts +11 -50
- package/dist/index.js +3 -122
- package/dist/node.cjs +83 -16
- package/dist/node.d.cts +5 -2
- package/dist/node.d.ts +5 -2
- package/dist/node.js +83 -17
- package/dist/{publish-CykUJfVa.cjs → publish-C7qHwEiP.cjs} +23 -0
- package/dist/{publish-DXoaC1Nl.js → publish-CyBj2o7n.js} +19 -2
- package/dist/{restore-BQp01WY3.js → restore-DVo1hXpN.js} +1 -1
- package/dist/{restore-CEywQUHz.cjs → restore-LXbDQqmT.cjs} +1 -1
- package/dist/uam-transaction.cjs +1 -1
- package/dist/uam-transaction.js +1 -1
- package/dist/web.cjs +46 -1
- package/dist/web.d.cts +5 -2
- package/dist/web.d.ts +5 -2
- package/dist/web.js +47 -3
- package/package.json +2 -2
- package/src/adapters/node/validate.ts +93 -0
- package/src/adapters/web/raster.ts +4 -0
- package/src/adapters/web/validate.ts +60 -0
- package/src/index.ts +2 -5
- package/src/node.ts +1 -0
- package/src/uam-transaction.ts +1 -1
- package/src/validate.ts +34 -183
- package/src/web.ts +1 -0
package/README.md
CHANGED
|
@@ -13,12 +13,13 @@ npm install --save @openfairygui/core @openfairygui/functions
|
|
|
13
13
|
```ts
|
|
14
14
|
import { NodeIO } from '@openfairygui/core/node';
|
|
15
15
|
import { inspect } from '@openfairygui/functions';
|
|
16
|
-
import { publishNode, restoreNode } from '@openfairygui/functions/node';
|
|
16
|
+
import { publishNode, restoreNode, validateProjectNode } from '@openfairygui/functions/node';
|
|
17
17
|
|
|
18
18
|
const io = new NodeIO();
|
|
19
19
|
const doc = await io.readProject('./MyProject/MyProject.fairy');
|
|
20
20
|
|
|
21
21
|
const report = inspect(doc);
|
|
22
|
+
const validation = await validateProjectNode('./MyProject/MyProject.fairy');
|
|
22
23
|
await publishNode({ document: doc, output: './release' });
|
|
23
24
|
|
|
24
25
|
await restoreNode({
|
|
@@ -27,17 +28,19 @@ await restoreNode({
|
|
|
27
28
|
});
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
`publishNode` owns the standard Node filesystem, Sharp raster backend, and project plugin discovery. `restoreNode` owns the Node filesystem and Sharp image extraction required by trusted-local artifact recovery. The root `publish()
|
|
31
|
+
`validateProjectNode` combines detailed project reads, UAM integrity checks, source checks, and Sharp image decoding without writing files. `publishNode` owns the standard Node filesystem, Sharp raster backend, and project plugin discovery. `restoreNode` owns the Node filesystem and Sharp image extraction required by trusted-local artifact recovery. The root `validateProject()`, `publish()`, and `restore()` exports remain lower-level workflows for custom hosts.
|
|
31
32
|
|
|
32
33
|
## Browser LayaBox publish
|
|
33
34
|
|
|
34
35
|
Use `@openfairygui/core/web` to read the raw project, then publish through the browser-only entry. Both filesystems are caller-owned, so they can be File System Access, OPFS, IndexedDB, ZIP, or memory adapters.
|
|
35
36
|
|
|
36
37
|
```ts
|
|
38
|
+
import { liftDocumentToUamProject } from '@openfairygui/core';
|
|
37
39
|
import { WebIO } from '@openfairygui/core/web';
|
|
38
|
-
import { publishBrowser } from '@openfairygui/functions/web';
|
|
40
|
+
import { publishBrowser, validateProjectWeb } from '@openfairygui/functions/web';
|
|
39
41
|
|
|
40
|
-
const document = await new WebIO(sourceFileSystem).readProject('Project.fairy');
|
|
42
|
+
const document = await new WebIO(sourceFileSystem).readProject('Project.fairy', { hydrateResourceBytes: true });
|
|
43
|
+
const validation = await validateProjectWeb(liftDocumentToUamProject(document));
|
|
41
44
|
const result = await publishBrowser({
|
|
42
45
|
document,
|
|
43
46
|
sourceFileSystem,
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_publish = require("./publish-
|
|
3
|
-
const require_restore = require("./restore-
|
|
2
|
+
const require_publish = require("./publish-C7qHwEiP.cjs");
|
|
3
|
+
const require_restore = require("./restore-LXbDQqmT.cjs");
|
|
4
4
|
const require_uam_transaction = require("./uam-transaction.cjs");
|
|
5
5
|
//#region src/inspect.ts
|
|
6
6
|
function mapResource(resource) {
|
|
@@ -104,125 +104,6 @@ function inspect(doc) {
|
|
|
104
104
|
};
|
|
105
105
|
}
|
|
106
106
|
//#endregion
|
|
107
|
-
//#region src/validate.ts
|
|
108
|
-
/**
|
|
109
|
-
* Severity of a validation issue.
|
|
110
|
-
*/
|
|
111
|
-
let ValidationSeverity = /* @__PURE__ */ function(ValidationSeverity) {
|
|
112
|
-
ValidationSeverity["ERROR"] = "error";
|
|
113
|
-
ValidationSeverity["WARNING"] = "warning";
|
|
114
|
-
ValidationSeverity["INFO"] = "info";
|
|
115
|
-
return ValidationSeverity;
|
|
116
|
-
}({});
|
|
117
|
-
const VALIDATE_DEFAULTS = { throwOnError: false };
|
|
118
|
-
/**
|
|
119
|
-
* Validates a FairyGUI project for common issues:
|
|
120
|
-
* - Missing resource IDs
|
|
121
|
-
* - Broken `ui://` references (src pointing to non-existent resources)
|
|
122
|
-
* - Empty components (no children)
|
|
123
|
-
* - Controllers with no pages
|
|
124
|
-
* - Duplicate resource IDs within a package
|
|
125
|
-
*
|
|
126
|
-
* The validation result is stored in `doc.getRoot().getExtras()._validation`.
|
|
127
|
-
*
|
|
128
|
-
* ```ts
|
|
129
|
-
* await doc.transform(validate({ throwOnError: true }));
|
|
130
|
-
* ```
|
|
131
|
-
*/
|
|
132
|
-
function validate(_options = {}) {
|
|
133
|
-
const options = {
|
|
134
|
-
...VALIDATE_DEFAULTS,
|
|
135
|
-
..._options
|
|
136
|
-
};
|
|
137
|
-
return require_publish.createTransform("validate", (doc) => {
|
|
138
|
-
const issues = [];
|
|
139
|
-
const root = doc.getRoot();
|
|
140
|
-
if (!root.getProjectId()) issues.push({
|
|
141
|
-
severity: ValidationSeverity.WARNING,
|
|
142
|
-
message: "Project has no ID."
|
|
143
|
-
});
|
|
144
|
-
const globalResources = /* @__PURE__ */ new Map();
|
|
145
|
-
for (const pkg of root.listPackages()) {
|
|
146
|
-
if (!pkg.getId()) issues.push({
|
|
147
|
-
severity: ValidationSeverity.ERROR,
|
|
148
|
-
message: `Package "${pkg.getName()}" has no ID.`,
|
|
149
|
-
packageName: pkg.getName()
|
|
150
|
-
});
|
|
151
|
-
const idSet = /* @__PURE__ */ new Set();
|
|
152
|
-
for (const res of pkg.listResources()) {
|
|
153
|
-
const resId = res.getId();
|
|
154
|
-
if (!resId) {
|
|
155
|
-
issues.push({
|
|
156
|
-
severity: ValidationSeverity.WARNING,
|
|
157
|
-
message: `Resource "${res.getName()}" has no ID.`,
|
|
158
|
-
packageName: pkg.getName(),
|
|
159
|
-
resourceName: res.getName()
|
|
160
|
-
});
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
if (idSet.has(resId)) issues.push({
|
|
164
|
-
severity: ValidationSeverity.ERROR,
|
|
165
|
-
message: `Duplicate resource ID "${resId}" in package "${pkg.getName()}".`,
|
|
166
|
-
packageName: pkg.getName(),
|
|
167
|
-
resourceName: res.getName()
|
|
168
|
-
});
|
|
169
|
-
idSet.add(resId);
|
|
170
|
-
globalResources.set(`${pkg.getId()}${resId}`, `${pkg.getName()}/${res.getName()}`);
|
|
171
|
-
}
|
|
172
|
-
for (const comp of pkg.listComponents()) {
|
|
173
|
-
const children = comp.listChildren();
|
|
174
|
-
if (children.length === 0) issues.push({
|
|
175
|
-
severity: ValidationSeverity.INFO,
|
|
176
|
-
message: `Component "${comp.getName()}" has no children.`,
|
|
177
|
-
packageName: pkg.getName(),
|
|
178
|
-
componentName: comp.getName()
|
|
179
|
-
});
|
|
180
|
-
for (const ctrl of comp.listControllers()) if (ctrl.listPages().length === 0) issues.push({
|
|
181
|
-
severity: ValidationSeverity.WARNING,
|
|
182
|
-
message: `Controller "${ctrl.getName()}" in "${comp.getName()}" has no pages.`,
|
|
183
|
-
packageName: pkg.getName(),
|
|
184
|
-
componentName: comp.getName()
|
|
185
|
-
});
|
|
186
|
-
for (const child of children) {
|
|
187
|
-
const src = child.getSrc?.();
|
|
188
|
-
if (!src) continue;
|
|
189
|
-
if (src.startsWith("ui://")) {
|
|
190
|
-
const idPart = src.slice(5);
|
|
191
|
-
if (idPart.length > 8) {
|
|
192
|
-
const key = `${idPart.slice(0, 8)}${idPart.slice(8)}`;
|
|
193
|
-
if (!globalResources.has(key)) issues.push({
|
|
194
|
-
severity: ValidationSeverity.ERROR,
|
|
195
|
-
message: `Broken reference "${src}" in "${child.getName()}" (component "${comp.getName()}").`,
|
|
196
|
-
packageName: pkg.getName(),
|
|
197
|
-
componentName: comp.getName(),
|
|
198
|
-
resourceName: child.getName()
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
const errors = issues.filter((i) => i.severity === ValidationSeverity.ERROR);
|
|
206
|
-
const warnings = issues.filter((i) => i.severity === ValidationSeverity.WARNING);
|
|
207
|
-
const infos = issues.filter((i) => i.severity === ValidationSeverity.INFO);
|
|
208
|
-
const result = {
|
|
209
|
-
ok: errors.length === 0,
|
|
210
|
-
errors,
|
|
211
|
-
warnings,
|
|
212
|
-
infos
|
|
213
|
-
};
|
|
214
|
-
root.setExtras({
|
|
215
|
-
...root.getExtras(),
|
|
216
|
-
_validation: result
|
|
217
|
-
});
|
|
218
|
-
const logger = doc.getLogger();
|
|
219
|
-
if (errors.length) logger.warn(`validate: ${errors.length} error(s) found.`);
|
|
220
|
-
if (warnings.length) logger.warn(`validate: ${warnings.length} warning(s) found.`);
|
|
221
|
-
logger.info(`validate: ${issues.length} issue(s) total.`);
|
|
222
|
-
if (options.throwOnError && errors.length > 0) throw new Error(`Validation failed with ${errors.length} error(s):\n${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
//#endregion
|
|
226
107
|
//#region src/prune.ts
|
|
227
108
|
const PRUNE_DEFAULTS = {
|
|
228
109
|
emptyComponents: false,
|
|
@@ -321,7 +202,6 @@ function rename(options) {
|
|
|
321
202
|
}
|
|
322
203
|
//#endregion
|
|
323
204
|
exports.AUTO_GENERATED_CODE_MARK = require_publish.AUTO_GENERATED_CODE_MARK;
|
|
324
|
-
exports.ValidationSeverity = ValidationSeverity;
|
|
325
205
|
exports.applyUamTransactionApp = require_uam_transaction.applyUamTransactionApp;
|
|
326
206
|
exports.applyUamTransactionAppAsync = require_uam_transaction.applyUamTransactionAppAsync;
|
|
327
207
|
exports.atlas = require_publish.atlas;
|
|
@@ -337,4 +217,4 @@ exports.rename = rename;
|
|
|
337
217
|
exports.resolvePackageCodegenPlan = require_publish.resolvePackageCodegenPlan;
|
|
338
218
|
exports.resolvePublishOptions = require_publish.resolvePublishOptions;
|
|
339
219
|
exports.restore = require_restore.restore;
|
|
340
|
-
exports.
|
|
220
|
+
exports.validateProject = require_publish.validateProject;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as AtlasRasterInput, c as AtlasRasterResolvedBuffer, d as PublishSourceFileSystem, i as AtlasRasterCompositeInput, l as PublishFileSystem, n as atlas, o as AtlasRasterMetadata, r as AtlasRasterBackend, s as AtlasRasterPipeline, t as AtlasOptions, u as PublishOutputFileSystem } from "./atlas-CHsu2Y8i.cjs";
|
|
2
2
|
import { A as ExtrasMap, B as ResolvedPublishOptions, C as MaybePromise, D as CliAtlasSettings, E as PluginModule, F as RootProjectSettings, I as publish, L as PublishOptions, M as HasOptionalSrc, N as HasOptionalUrl, O as CliCodeGenerationSettings, P as PublishDependency, R as ResolvePublishOptionsOverrides, S as LoadedPlugin, T as PluginManifest, V as resolvePublishOptions, _ as encodeText, a as RestoreImageExtractor, b as CodeWriter, c as restore, d as CodegenMember, f as CodegenReferencedComponent, g as decodeText, h as buildCodegenClasses, i as RestoreImageExtractInput, j as HasOptionalFont, k as CliPublishSettings, l as AUTO_GENERATED_CODE_MARK, m as ResolvedPackageCodegenPlan, n as RestoreImageCropInput, o as RestoreOptions, p as PublishCodeGenerationOptions, r as RestoreImageCropper, s as RestoreResult, t as RestoreFileSystem, u as CodegenClass, v as publishCodeGeneration, w as Plugin, x as ICodeWriterConfig, y as resolvePackageCodegenPlan, z as ResolvedPublishAtlasOptions } from "./restore-BeWaJNjR.cjs";
|
|
3
3
|
import { ApplyUamTransactionAppDiagnostic, ApplyUamTransactionAppError, ApplyUamTransactionAppInput, ApplyUamTransactionAppResult, applyUamTransactionApp, applyUamTransactionAppAsync } from "./uam-transaction.cjs";
|
|
4
|
-
import { Document, Transform } from "@openfairygui/core";
|
|
4
|
+
import { Document, ProjectDiagnostic, ProjectValidationReport, Transform, UamProject } from "@openfairygui/core";
|
|
5
5
|
|
|
6
6
|
//#region src/inspect.d.ts
|
|
7
7
|
/**
|
|
@@ -69,55 +69,16 @@ interface InspectReport {
|
|
|
69
69
|
declare function inspect(doc: Document): InspectReport;
|
|
70
70
|
//#endregion
|
|
71
71
|
//#region src/validate.d.ts
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* A single validation issue found in the project.
|
|
82
|
-
*/
|
|
83
|
-
interface ValidationIssue {
|
|
84
|
-
severity: ValidationSeverity;
|
|
85
|
-
message: string;
|
|
86
|
-
/** Package name where the issue was found. */
|
|
87
|
-
packageName?: string;
|
|
88
|
-
/** Component name where the issue was found. */
|
|
89
|
-
componentName?: string;
|
|
90
|
-
/** Resource/object name related to the issue. */
|
|
91
|
-
resourceName?: string;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Result returned by `validate()`.
|
|
95
|
-
*/
|
|
96
|
-
interface ValidationResult {
|
|
97
|
-
ok: boolean;
|
|
98
|
-
errors: ValidationIssue[];
|
|
99
|
-
warnings: ValidationIssue[];
|
|
100
|
-
infos: ValidationIssue[];
|
|
72
|
+
interface ValidateProjectOptions {
|
|
73
|
+
/** Diagnostics collected while reading the source project. */
|
|
74
|
+
readDiagnostics?: readonly ProjectDiagnostic[];
|
|
75
|
+
/** Whether the reader and host completed every requested check. */
|
|
76
|
+
complete?: boolean;
|
|
77
|
+
/** Validate hydrated resource bytes in addition to the UAM graph. */
|
|
78
|
+
validateSources?: boolean;
|
|
101
79
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
throwOnError?: boolean;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Validates a FairyGUI project for common issues:
|
|
108
|
-
* - Missing resource IDs
|
|
109
|
-
* - Broken `ui://` references (src pointing to non-existent resources)
|
|
110
|
-
* - Empty components (no children)
|
|
111
|
-
* - Controllers with no pages
|
|
112
|
-
* - Duplicate resource IDs within a package
|
|
113
|
-
*
|
|
114
|
-
* The validation result is stored in `doc.getRoot().getExtras()._validation`.
|
|
115
|
-
*
|
|
116
|
-
* ```ts
|
|
117
|
-
* await doc.transform(validate({ throwOnError: true }));
|
|
118
|
-
* ```
|
|
119
|
-
*/
|
|
120
|
-
declare function validate(_options?: ValidateOptions): Transform;
|
|
80
|
+
/** Validate one authoritative UAM snapshot without mutating it. */
|
|
81
|
+
declare function validateProject(project: UamProject, options?: ValidateProjectOptions): ProjectValidationReport;
|
|
121
82
|
//#endregion
|
|
122
83
|
//#region src/prune.d.ts
|
|
123
84
|
interface PruneOptions {
|
|
@@ -174,4 +135,4 @@ declare function rename(options: RenameOptions): Transform;
|
|
|
174
135
|
*/
|
|
175
136
|
declare function createTransform(name: string, fn: Transform): Transform;
|
|
176
137
|
//#endregion
|
|
177
|
-
export { AUTO_GENERATED_CODE_MARK, type ApplyUamTransactionAppDiagnostic, type ApplyUamTransactionAppError, type ApplyUamTransactionAppInput, type ApplyUamTransactionAppResult, type AtlasOptions, type AtlasRasterBackend, type AtlasRasterCompositeInput, type AtlasRasterInput, type AtlasRasterMetadata, type AtlasRasterPipeline, type AtlasRasterResolvedBuffer, type CliAtlasSettings, type CliCodeGenerationSettings, type CliPublishSettings, type CodeWriter, type CodegenClass, type CodegenMember, type CodegenReferencedComponent, type ExtrasMap, type HasOptionalFont, type HasOptionalSrc, type HasOptionalUrl, type ICodeWriterConfig, type InspectCategoryReport, type InspectReport, type LoadedPlugin, type MaybePromise, type Plugin, type PluginManifest, type PluginModule, type PruneOptions, type PublishCodeGenerationOptions, type PublishDependency, type PublishFileSystem, type PublishOptions, type PublishOutputFileSystem, type PublishSourceFileSystem, type RenameOptions, type ResolvePublishOptionsOverrides, type ResolvedPackageCodegenPlan, type ResolvedPublishAtlasOptions, type ResolvedPublishOptions, type RestoreFileSystem, type RestoreImageCropInput, type RestoreImageCropper, type RestoreImageExtractInput, type RestoreImageExtractor, type RestoreOptions, type RestoreResult, type RootProjectSettings, type
|
|
138
|
+
export { AUTO_GENERATED_CODE_MARK, type ApplyUamTransactionAppDiagnostic, type ApplyUamTransactionAppError, type ApplyUamTransactionAppInput, type ApplyUamTransactionAppResult, type AtlasOptions, type AtlasRasterBackend, type AtlasRasterCompositeInput, type AtlasRasterInput, type AtlasRasterMetadata, type AtlasRasterPipeline, type AtlasRasterResolvedBuffer, type CliAtlasSettings, type CliCodeGenerationSettings, type CliPublishSettings, type CodeWriter, type CodegenClass, type CodegenMember, type CodegenReferencedComponent, type ExtrasMap, type HasOptionalFont, type HasOptionalSrc, type HasOptionalUrl, type ICodeWriterConfig, type InspectCategoryReport, type InspectReport, type LoadedPlugin, type MaybePromise, type Plugin, type PluginManifest, type PluginModule, type PruneOptions, type PublishCodeGenerationOptions, type PublishDependency, type PublishFileSystem, type PublishOptions, type PublishOutputFileSystem, type PublishSourceFileSystem, type RenameOptions, type ResolvePublishOptionsOverrides, type ResolvedPackageCodegenPlan, type ResolvedPublishAtlasOptions, type ResolvedPublishOptions, type RestoreFileSystem, type RestoreImageCropInput, type RestoreImageCropper, type RestoreImageExtractInput, type RestoreImageExtractor, type RestoreOptions, type RestoreResult, type RootProjectSettings, type ValidateProjectOptions, applyUamTransactionApp, applyUamTransactionAppAsync, atlas, buildCodegenClasses, createTransform, decodeText, encodeText, inspect, prune, publish, publishCodeGeneration, rename, resolvePackageCodegenPlan, resolvePublishOptions, restore, validateProject };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as AtlasRasterInput, c as AtlasRasterResolvedBuffer, d as PublishSourceFileSystem, i as AtlasRasterCompositeInput, l as PublishFileSystem, n as atlas, o as AtlasRasterMetadata, r as AtlasRasterBackend, s as AtlasRasterPipeline, t as AtlasOptions, u as PublishOutputFileSystem } from "./atlas-C6tbl7nn.js";
|
|
2
2
|
import { A as ExtrasMap, B as ResolvedPublishOptions, C as MaybePromise, D as CliAtlasSettings, E as PluginModule, F as RootProjectSettings, I as publish, L as PublishOptions, M as HasOptionalSrc, N as HasOptionalUrl, O as CliCodeGenerationSettings, P as PublishDependency, R as ResolvePublishOptionsOverrides, S as LoadedPlugin, T as PluginManifest, V as resolvePublishOptions, _ as encodeText, a as RestoreImageExtractor, b as CodeWriter, c as restore, d as CodegenMember, f as CodegenReferencedComponent, g as decodeText, h as buildCodegenClasses, i as RestoreImageExtractInput, j as HasOptionalFont, k as CliPublishSettings, l as AUTO_GENERATED_CODE_MARK, m as ResolvedPackageCodegenPlan, n as RestoreImageCropInput, o as RestoreOptions, p as PublishCodeGenerationOptions, r as RestoreImageCropper, s as RestoreResult, t as RestoreFileSystem, u as CodegenClass, v as publishCodeGeneration, w as Plugin, x as ICodeWriterConfig, y as resolvePackageCodegenPlan, z as ResolvedPublishAtlasOptions } from "./restore-Dh0-Nvms.js";
|
|
3
3
|
import { ApplyUamTransactionAppDiagnostic, ApplyUamTransactionAppError, ApplyUamTransactionAppInput, ApplyUamTransactionAppResult, applyUamTransactionApp, applyUamTransactionAppAsync } from "./uam-transaction.js";
|
|
4
|
-
import { Document, Transform } from "@openfairygui/core";
|
|
4
|
+
import { Document, ProjectDiagnostic, ProjectValidationReport, Transform, UamProject } from "@openfairygui/core";
|
|
5
5
|
|
|
6
6
|
//#region src/inspect.d.ts
|
|
7
7
|
/**
|
|
@@ -69,55 +69,16 @@ interface InspectReport {
|
|
|
69
69
|
declare function inspect(doc: Document): InspectReport;
|
|
70
70
|
//#endregion
|
|
71
71
|
//#region src/validate.d.ts
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* A single validation issue found in the project.
|
|
82
|
-
*/
|
|
83
|
-
interface ValidationIssue {
|
|
84
|
-
severity: ValidationSeverity;
|
|
85
|
-
message: string;
|
|
86
|
-
/** Package name where the issue was found. */
|
|
87
|
-
packageName?: string;
|
|
88
|
-
/** Component name where the issue was found. */
|
|
89
|
-
componentName?: string;
|
|
90
|
-
/** Resource/object name related to the issue. */
|
|
91
|
-
resourceName?: string;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Result returned by `validate()`.
|
|
95
|
-
*/
|
|
96
|
-
interface ValidationResult {
|
|
97
|
-
ok: boolean;
|
|
98
|
-
errors: ValidationIssue[];
|
|
99
|
-
warnings: ValidationIssue[];
|
|
100
|
-
infos: ValidationIssue[];
|
|
72
|
+
interface ValidateProjectOptions {
|
|
73
|
+
/** Diagnostics collected while reading the source project. */
|
|
74
|
+
readDiagnostics?: readonly ProjectDiagnostic[];
|
|
75
|
+
/** Whether the reader and host completed every requested check. */
|
|
76
|
+
complete?: boolean;
|
|
77
|
+
/** Validate hydrated resource bytes in addition to the UAM graph. */
|
|
78
|
+
validateSources?: boolean;
|
|
101
79
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
throwOnError?: boolean;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Validates a FairyGUI project for common issues:
|
|
108
|
-
* - Missing resource IDs
|
|
109
|
-
* - Broken `ui://` references (src pointing to non-existent resources)
|
|
110
|
-
* - Empty components (no children)
|
|
111
|
-
* - Controllers with no pages
|
|
112
|
-
* - Duplicate resource IDs within a package
|
|
113
|
-
*
|
|
114
|
-
* The validation result is stored in `doc.getRoot().getExtras()._validation`.
|
|
115
|
-
*
|
|
116
|
-
* ```ts
|
|
117
|
-
* await doc.transform(validate({ throwOnError: true }));
|
|
118
|
-
* ```
|
|
119
|
-
*/
|
|
120
|
-
declare function validate(_options?: ValidateOptions): Transform;
|
|
80
|
+
/** Validate one authoritative UAM snapshot without mutating it. */
|
|
81
|
+
declare function validateProject(project: UamProject, options?: ValidateProjectOptions): ProjectValidationReport;
|
|
121
82
|
//#endregion
|
|
122
83
|
//#region src/prune.d.ts
|
|
123
84
|
interface PruneOptions {
|
|
@@ -174,4 +135,4 @@ declare function rename(options: RenameOptions): Transform;
|
|
|
174
135
|
*/
|
|
175
136
|
declare function createTransform(name: string, fn: Transform): Transform;
|
|
176
137
|
//#endregion
|
|
177
|
-
export { AUTO_GENERATED_CODE_MARK, type ApplyUamTransactionAppDiagnostic, type ApplyUamTransactionAppError, type ApplyUamTransactionAppInput, type ApplyUamTransactionAppResult, type AtlasOptions, type AtlasRasterBackend, type AtlasRasterCompositeInput, type AtlasRasterInput, type AtlasRasterMetadata, type AtlasRasterPipeline, type AtlasRasterResolvedBuffer, type CliAtlasSettings, type CliCodeGenerationSettings, type CliPublishSettings, type CodeWriter, type CodegenClass, type CodegenMember, type CodegenReferencedComponent, type ExtrasMap, type HasOptionalFont, type HasOptionalSrc, type HasOptionalUrl, type ICodeWriterConfig, type InspectCategoryReport, type InspectReport, type LoadedPlugin, type MaybePromise, type Plugin, type PluginManifest, type PluginModule, type PruneOptions, type PublishCodeGenerationOptions, type PublishDependency, type PublishFileSystem, type PublishOptions, type PublishOutputFileSystem, type PublishSourceFileSystem, type RenameOptions, type ResolvePublishOptionsOverrides, type ResolvedPackageCodegenPlan, type ResolvedPublishAtlasOptions, type ResolvedPublishOptions, type RestoreFileSystem, type RestoreImageCropInput, type RestoreImageCropper, type RestoreImageExtractInput, type RestoreImageExtractor, type RestoreOptions, type RestoreResult, type RootProjectSettings, type
|
|
138
|
+
export { AUTO_GENERATED_CODE_MARK, type ApplyUamTransactionAppDiagnostic, type ApplyUamTransactionAppError, type ApplyUamTransactionAppInput, type ApplyUamTransactionAppResult, type AtlasOptions, type AtlasRasterBackend, type AtlasRasterCompositeInput, type AtlasRasterInput, type AtlasRasterMetadata, type AtlasRasterPipeline, type AtlasRasterResolvedBuffer, type CliAtlasSettings, type CliCodeGenerationSettings, type CliPublishSettings, type CodeWriter, type CodegenClass, type CodegenMember, type CodegenReferencedComponent, type ExtrasMap, type HasOptionalFont, type HasOptionalSrc, type HasOptionalUrl, type ICodeWriterConfig, type InspectCategoryReport, type InspectReport, type LoadedPlugin, type MaybePromise, type Plugin, type PluginManifest, type PluginModule, type PruneOptions, type PublishCodeGenerationOptions, type PublishDependency, type PublishFileSystem, type PublishOptions, type PublishOutputFileSystem, type PublishSourceFileSystem, type RenameOptions, type ResolvePublishOptionsOverrides, type ResolvedPackageCodegenPlan, type ResolvedPublishAtlasOptions, type ResolvedPublishOptions, type RestoreFileSystem, type RestoreImageCropInput, type RestoreImageCropper, type RestoreImageExtractInput, type RestoreImageExtractor, type RestoreOptions, type RestoreResult, type RootProjectSettings, type ValidateProjectOptions, applyUamTransactionApp, applyUamTransactionAppAsync, atlas, buildCodegenClasses, createTransform, decodeText, encodeText, inspect, prune, publish, publishCodeGeneration, rename, resolvePackageCodegenPlan, resolvePublishOptions, restore, validateProject };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as decodeText, g as createTransform, h as atlas, i as buildCodegenClasses, l as resolvePackageCodegenPlan, n as resolvePublishOptions, o as encodeText, r as AUTO_GENERATED_CODE_MARK, s as publishCodeGeneration, t as publish } from "./publish-
|
|
2
|
-
import { t as restore } from "./restore-
|
|
1
|
+
import { _ as validateProject, a as decodeText, g as createTransform, h as atlas, i as buildCodegenClasses, l as resolvePackageCodegenPlan, n as resolvePublishOptions, o as encodeText, r as AUTO_GENERATED_CODE_MARK, s as publishCodeGeneration, t as publish } from "./publish-CyBj2o7n.js";
|
|
2
|
+
import { t as restore } from "./restore-DVo1hXpN.js";
|
|
3
3
|
import { applyUamTransactionApp, applyUamTransactionAppAsync } from "./uam-transaction.js";
|
|
4
4
|
//#region src/inspect.ts
|
|
5
5
|
function mapResource(resource) {
|
|
@@ -103,125 +103,6 @@ function inspect(doc) {
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
//#endregion
|
|
106
|
-
//#region src/validate.ts
|
|
107
|
-
/**
|
|
108
|
-
* Severity of a validation issue.
|
|
109
|
-
*/
|
|
110
|
-
let ValidationSeverity = /* @__PURE__ */ function(ValidationSeverity) {
|
|
111
|
-
ValidationSeverity["ERROR"] = "error";
|
|
112
|
-
ValidationSeverity["WARNING"] = "warning";
|
|
113
|
-
ValidationSeverity["INFO"] = "info";
|
|
114
|
-
return ValidationSeverity;
|
|
115
|
-
}({});
|
|
116
|
-
const VALIDATE_DEFAULTS = { throwOnError: false };
|
|
117
|
-
/**
|
|
118
|
-
* Validates a FairyGUI project for common issues:
|
|
119
|
-
* - Missing resource IDs
|
|
120
|
-
* - Broken `ui://` references (src pointing to non-existent resources)
|
|
121
|
-
* - Empty components (no children)
|
|
122
|
-
* - Controllers with no pages
|
|
123
|
-
* - Duplicate resource IDs within a package
|
|
124
|
-
*
|
|
125
|
-
* The validation result is stored in `doc.getRoot().getExtras()._validation`.
|
|
126
|
-
*
|
|
127
|
-
* ```ts
|
|
128
|
-
* await doc.transform(validate({ throwOnError: true }));
|
|
129
|
-
* ```
|
|
130
|
-
*/
|
|
131
|
-
function validate(_options = {}) {
|
|
132
|
-
const options = {
|
|
133
|
-
...VALIDATE_DEFAULTS,
|
|
134
|
-
..._options
|
|
135
|
-
};
|
|
136
|
-
return createTransform("validate", (doc) => {
|
|
137
|
-
const issues = [];
|
|
138
|
-
const root = doc.getRoot();
|
|
139
|
-
if (!root.getProjectId()) issues.push({
|
|
140
|
-
severity: ValidationSeverity.WARNING,
|
|
141
|
-
message: "Project has no ID."
|
|
142
|
-
});
|
|
143
|
-
const globalResources = /* @__PURE__ */ new Map();
|
|
144
|
-
for (const pkg of root.listPackages()) {
|
|
145
|
-
if (!pkg.getId()) issues.push({
|
|
146
|
-
severity: ValidationSeverity.ERROR,
|
|
147
|
-
message: `Package "${pkg.getName()}" has no ID.`,
|
|
148
|
-
packageName: pkg.getName()
|
|
149
|
-
});
|
|
150
|
-
const idSet = /* @__PURE__ */ new Set();
|
|
151
|
-
for (const res of pkg.listResources()) {
|
|
152
|
-
const resId = res.getId();
|
|
153
|
-
if (!resId) {
|
|
154
|
-
issues.push({
|
|
155
|
-
severity: ValidationSeverity.WARNING,
|
|
156
|
-
message: `Resource "${res.getName()}" has no ID.`,
|
|
157
|
-
packageName: pkg.getName(),
|
|
158
|
-
resourceName: res.getName()
|
|
159
|
-
});
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
if (idSet.has(resId)) issues.push({
|
|
163
|
-
severity: ValidationSeverity.ERROR,
|
|
164
|
-
message: `Duplicate resource ID "${resId}" in package "${pkg.getName()}".`,
|
|
165
|
-
packageName: pkg.getName(),
|
|
166
|
-
resourceName: res.getName()
|
|
167
|
-
});
|
|
168
|
-
idSet.add(resId);
|
|
169
|
-
globalResources.set(`${pkg.getId()}${resId}`, `${pkg.getName()}/${res.getName()}`);
|
|
170
|
-
}
|
|
171
|
-
for (const comp of pkg.listComponents()) {
|
|
172
|
-
const children = comp.listChildren();
|
|
173
|
-
if (children.length === 0) issues.push({
|
|
174
|
-
severity: ValidationSeverity.INFO,
|
|
175
|
-
message: `Component "${comp.getName()}" has no children.`,
|
|
176
|
-
packageName: pkg.getName(),
|
|
177
|
-
componentName: comp.getName()
|
|
178
|
-
});
|
|
179
|
-
for (const ctrl of comp.listControllers()) if (ctrl.listPages().length === 0) issues.push({
|
|
180
|
-
severity: ValidationSeverity.WARNING,
|
|
181
|
-
message: `Controller "${ctrl.getName()}" in "${comp.getName()}" has no pages.`,
|
|
182
|
-
packageName: pkg.getName(),
|
|
183
|
-
componentName: comp.getName()
|
|
184
|
-
});
|
|
185
|
-
for (const child of children) {
|
|
186
|
-
const src = child.getSrc?.();
|
|
187
|
-
if (!src) continue;
|
|
188
|
-
if (src.startsWith("ui://")) {
|
|
189
|
-
const idPart = src.slice(5);
|
|
190
|
-
if (idPart.length > 8) {
|
|
191
|
-
const key = `${idPart.slice(0, 8)}${idPart.slice(8)}`;
|
|
192
|
-
if (!globalResources.has(key)) issues.push({
|
|
193
|
-
severity: ValidationSeverity.ERROR,
|
|
194
|
-
message: `Broken reference "${src}" in "${child.getName()}" (component "${comp.getName()}").`,
|
|
195
|
-
packageName: pkg.getName(),
|
|
196
|
-
componentName: comp.getName(),
|
|
197
|
-
resourceName: child.getName()
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
const errors = issues.filter((i) => i.severity === ValidationSeverity.ERROR);
|
|
205
|
-
const warnings = issues.filter((i) => i.severity === ValidationSeverity.WARNING);
|
|
206
|
-
const infos = issues.filter((i) => i.severity === ValidationSeverity.INFO);
|
|
207
|
-
const result = {
|
|
208
|
-
ok: errors.length === 0,
|
|
209
|
-
errors,
|
|
210
|
-
warnings,
|
|
211
|
-
infos
|
|
212
|
-
};
|
|
213
|
-
root.setExtras({
|
|
214
|
-
...root.getExtras(),
|
|
215
|
-
_validation: result
|
|
216
|
-
});
|
|
217
|
-
const logger = doc.getLogger();
|
|
218
|
-
if (errors.length) logger.warn(`validate: ${errors.length} error(s) found.`);
|
|
219
|
-
if (warnings.length) logger.warn(`validate: ${warnings.length} warning(s) found.`);
|
|
220
|
-
logger.info(`validate: ${issues.length} issue(s) total.`);
|
|
221
|
-
if (options.throwOnError && errors.length > 0) throw new Error(`Validation failed with ${errors.length} error(s):\n${errors.map((e) => ` - ${e.message}`).join("\n")}`);
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
//#endregion
|
|
225
106
|
//#region src/prune.ts
|
|
226
107
|
const PRUNE_DEFAULTS = {
|
|
227
108
|
emptyComponents: false,
|
|
@@ -319,4 +200,4 @@ function rename(options) {
|
|
|
319
200
|
});
|
|
320
201
|
}
|
|
321
202
|
//#endregion
|
|
322
|
-
export { AUTO_GENERATED_CODE_MARK,
|
|
203
|
+
export { AUTO_GENERATED_CODE_MARK, applyUamTransactionApp, applyUamTransactionAppAsync, atlas, buildCodegenClasses, createTransform, decodeText, encodeText, inspect, prune, publish, publishCodeGeneration, rename, resolvePackageCodegenPlan, resolvePublishOptions, restore, validateProject };
|
package/dist/node.cjs
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_publish = require("./publish-
|
|
3
|
-
const require_restore = require("./restore-
|
|
2
|
+
const require_publish = require("./publish-C7qHwEiP.cjs");
|
|
3
|
+
const require_restore = require("./restore-LXbDQqmT.cjs");
|
|
4
|
+
let _openfairygui_core = require("@openfairygui/core");
|
|
5
|
+
let _openfairygui_core_node = require("@openfairygui/core/node");
|
|
4
6
|
//#region src/adapters/node/plugins.ts
|
|
5
|
-
const importNative$
|
|
7
|
+
const importNative$3 = new Function("id", "return import(id)");
|
|
6
8
|
async function loadPlugins(doc, pluginsDir) {
|
|
7
9
|
if (!pluginsDir) return [];
|
|
8
|
-
const fs = await importNative$
|
|
9
|
-
const path = await importNative$
|
|
10
|
+
const fs = await importNative$3("node:fs/promises");
|
|
11
|
+
const path = await importNative$3("node:path");
|
|
10
12
|
let entries;
|
|
11
13
|
try {
|
|
12
14
|
entries = await fs.readdir(pluginsDir, { withFileTypes: true });
|
|
@@ -46,7 +48,7 @@ function resolvePluginMain(path, pluginDir, manifest) {
|
|
|
46
48
|
return mainPath;
|
|
47
49
|
}
|
|
48
50
|
async function loadPlugin(mainPath) {
|
|
49
|
-
const { createJiti } = await importNative$
|
|
51
|
+
const { createJiti } = await importNative$3("jiti");
|
|
50
52
|
const mod = await createJiti(require("url").pathToFileURL(__filename).href).import(mainPath);
|
|
51
53
|
const defaultExport = mod.default;
|
|
52
54
|
return isObject(defaultExport) ? defaultExport : mod;
|
|
@@ -56,9 +58,9 @@ function isObject(value) {
|
|
|
56
58
|
}
|
|
57
59
|
//#endregion
|
|
58
60
|
//#region src/adapters/node/publish.ts
|
|
59
|
-
const importNative$
|
|
61
|
+
const importNative$2 = new Function("id", "return import(id)");
|
|
60
62
|
async function createNodePublishFileSystem() {
|
|
61
|
-
const [fs, path] = await Promise.all([importNative$
|
|
63
|
+
const [fs, path] = await Promise.all([importNative$2("node:fs/promises"), importNative$2("node:path")]);
|
|
62
64
|
return {
|
|
63
65
|
async readFileRaw(filePath) {
|
|
64
66
|
const data = await fs.readFile(filePath);
|
|
@@ -86,11 +88,11 @@ async function resolveNodeAssetsPath(document, assetsPath) {
|
|
|
86
88
|
if (assetsPath) return assetsPath;
|
|
87
89
|
const projectDir = document.getProjectDir?.() ?? "";
|
|
88
90
|
if (!projectDir) return void 0;
|
|
89
|
-
return (await importNative$
|
|
91
|
+
return (await importNative$2("node:path")).join(projectDir, "assets");
|
|
90
92
|
}
|
|
91
93
|
async function loadSharpBackend() {
|
|
92
94
|
try {
|
|
93
|
-
const loaded = await importNative$
|
|
95
|
+
const loaded = await importNative$2("sharp");
|
|
94
96
|
return loaded.default ?? loaded;
|
|
95
97
|
} catch {
|
|
96
98
|
return;
|
|
@@ -99,7 +101,7 @@ async function loadSharpBackend() {
|
|
|
99
101
|
async function loadNodePublishPlugins(document, assetsPath) {
|
|
100
102
|
const projectDir = document.getProjectDir?.() || (assetsPath ? require_publish.resolveProjectBasePath(assetsPath) : "");
|
|
101
103
|
if (!projectDir) return [];
|
|
102
|
-
return loadPlugins(document, (await importNative$
|
|
104
|
+
return loadPlugins(document, (await importNative$2("node:path")).join(projectDir, "plugins"));
|
|
103
105
|
}
|
|
104
106
|
/**
|
|
105
107
|
* Publish a FairyGUI project through the standard Node host adapter.
|
|
@@ -127,9 +129,9 @@ async function publishNode(options) {
|
|
|
127
129
|
}
|
|
128
130
|
//#endregion
|
|
129
131
|
//#region src/adapters/node/restore.ts
|
|
130
|
-
const importNative = new Function("id", "return import(id)");
|
|
132
|
+
const importNative$1 = new Function("id", "return import(id)");
|
|
131
133
|
async function createNodeRestoreFileSystem() {
|
|
132
|
-
const [fs, path] = await Promise.all([importNative("node:fs/promises"), importNative("node:path")]);
|
|
134
|
+
const [fs, path] = await Promise.all([importNative$1("node:fs/promises"), importNative$1("node:path")]);
|
|
133
135
|
return {
|
|
134
136
|
async readFile(filePath) {
|
|
135
137
|
return fs.readFile(filePath, "utf-8");
|
|
@@ -194,7 +196,7 @@ async function createNodeRestoreFileSystem() {
|
|
|
194
196
|
async function createRestoreImageProcessors() {
|
|
195
197
|
let sharp;
|
|
196
198
|
try {
|
|
197
|
-
const loaded = await importNative("sharp");
|
|
199
|
+
const loaded = await importNative$1("sharp");
|
|
198
200
|
sharp = loaded.default ?? loaded;
|
|
199
201
|
} catch {
|
|
200
202
|
throw new Error("restoreNode: Sharp is required to crop atlas images. Install sharp before restoring.");
|
|
@@ -232,8 +234,8 @@ async function createRestoreImageProcessors() {
|
|
|
232
234
|
if (input.expectedWidth > 0 && input.expectedHeight > 0 && (info.width !== input.expectedWidth || info.height !== input.expectedHeight)) throw new Error(`restore: Cropped image size mismatch for ${targetPath}: expected ${input.expectedWidth}x${input.expectedHeight}, got ${info.width}x${info.height}`);
|
|
233
235
|
return data;
|
|
234
236
|
}
|
|
235
|
-
const fs = await importNative("node:fs/promises");
|
|
236
|
-
const path = await importNative("node:path");
|
|
237
|
+
const fs = await importNative$1("node:fs/promises");
|
|
238
|
+
const path = await importNative$1("node:path");
|
|
237
239
|
return {
|
|
238
240
|
extractImage,
|
|
239
241
|
cropImage: async (input) => {
|
|
@@ -252,5 +254,70 @@ async function restoreNode(options) {
|
|
|
252
254
|
});
|
|
253
255
|
}
|
|
254
256
|
//#endregion
|
|
257
|
+
//#region src/adapters/node/validate.ts
|
|
258
|
+
const importNative = new Function("id", "return import(id)");
|
|
259
|
+
function sourceName(resource) {
|
|
260
|
+
return resource.sourcePath ?? resource.fileName ?? resource.file ?? resource.name;
|
|
261
|
+
}
|
|
262
|
+
async function validateProjectNode(projectPath) {
|
|
263
|
+
const read = await new _openfairygui_core_node.NodeIO().readProjectDetailed(projectPath, { hydrateResourceBytes: true });
|
|
264
|
+
if (!read.document) return (0, _openfairygui_core.createProjectValidationReport)(read.diagnostics, false);
|
|
265
|
+
let project;
|
|
266
|
+
try {
|
|
267
|
+
project = (0, _openfairygui_core.liftDocumentToUamProject)(read.document);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
return (0, _openfairygui_core.createProjectValidationReport)([...read.diagnostics, {
|
|
270
|
+
severity: "error",
|
|
271
|
+
code: "invalid_uam",
|
|
272
|
+
path: "project",
|
|
273
|
+
message: `Project cannot be represented as UAM: ${error instanceof Error ? error.message : String(error)}`,
|
|
274
|
+
sourcePath: projectPath
|
|
275
|
+
}], false);
|
|
276
|
+
}
|
|
277
|
+
const base = require_publish.validateProject(project, {
|
|
278
|
+
readDiagnostics: read.diagnostics,
|
|
279
|
+
complete: read.complete,
|
|
280
|
+
validateSources: true
|
|
281
|
+
});
|
|
282
|
+
let diagnostics = base.diagnostics;
|
|
283
|
+
const knownCorruptPaths = new Set(base.diagnostics.filter((diagnostic) => diagnostic.code === "corrupt_source").map((diagnostic) => diagnostic.path));
|
|
284
|
+
const images = project.packages.flatMap((pkg, packageIndex) => pkg.resources.map((resource, resourceIndex) => ({
|
|
285
|
+
pkg,
|
|
286
|
+
packageIndex,
|
|
287
|
+
resource,
|
|
288
|
+
resourceIndex
|
|
289
|
+
})).filter(({ resource, packageIndex, resourceIndex }) => resource.kind === "image" && resource.sourceBytes instanceof Uint8Array && !knownCorruptPaths.has(`packages[${packageIndex}].resources[${resourceIndex}]`)));
|
|
290
|
+
if (images.length === 0) return base;
|
|
291
|
+
let sharp;
|
|
292
|
+
try {
|
|
293
|
+
const loaded = await importNative("sharp");
|
|
294
|
+
sharp = loaded.default ?? loaded;
|
|
295
|
+
} catch {
|
|
296
|
+
return (0, _openfairygui_core.createProjectValidationReport)([...base.diagnostics, {
|
|
297
|
+
severity: "warning",
|
|
298
|
+
code: "decode_capability_unavailable",
|
|
299
|
+
path: "project",
|
|
300
|
+
message: "Sharp is unavailable, so Node image decoding could not be completed."
|
|
301
|
+
}], false);
|
|
302
|
+
}
|
|
303
|
+
const decodedPaths = new Set(images.map(({ packageIndex, resourceIndex }) => `packages[${packageIndex}].resources[${resourceIndex}]`));
|
|
304
|
+
diagnostics = diagnostics.filter((diagnostic) => diagnostic.code !== "decode_capability_unavailable" || !decodedPaths.has(diagnostic.path));
|
|
305
|
+
for (const { pkg, packageIndex, resource, resourceIndex } of images) try {
|
|
306
|
+
await sharp(resource.sourceBytes).raw().toBuffer();
|
|
307
|
+
} catch (error) {
|
|
308
|
+
diagnostics.push({
|
|
309
|
+
severity: "error",
|
|
310
|
+
code: "corrupt_source",
|
|
311
|
+
path: `packages[${packageIndex}].resources[${resourceIndex}]`,
|
|
312
|
+
message: `Image source cannot be decoded: ${error instanceof Error ? error.message : String(error)}`,
|
|
313
|
+
packageId: pkg.id,
|
|
314
|
+
resourceId: resource.id,
|
|
315
|
+
sourcePath: sourceName(resource)
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
return (0, _openfairygui_core.createProjectValidationReport)(diagnostics, read.complete && !diagnostics.some((diagnostic) => diagnostic.code === "decode_capability_unavailable"));
|
|
319
|
+
}
|
|
320
|
+
//#endregion
|
|
255
321
|
exports.publishNode = publishNode;
|
|
256
322
|
exports.restoreNode = restoreNode;
|
|
323
|
+
exports.validateProjectNode = validateProjectNode;
|